http-rs / tide

Fast and friendly HTTP server framework for async Rust
https://docs.rs/tide
Apache License 2.0
5.06k stars 321 forks source link

Consider having feature flags for all built-in middleware. #548

Open Fishrock123 opened 4 years ago

Fishrock123 commented 4 years ago

It's not inconceivable that people may want to disable any particularly built in middleware. Particularly the logger middleware, but it's not inconceivable that someone may want to disable even the cookies one for some reason.

These would still be on by default.

jbr commented 4 years ago

It seems like this could be achieved without compiler feature flags, in code:

let mut app = tide::configure().skip_logger().with_state(state).build()

since it doesn't seem terribly unlikely tide will need some general way to optionally configure other aspects of the Server in code at some point

bluk commented 4 years ago

I would prefer an explicit way to specify that no middleware should be added (versus having to discover any middleware added in every release and finding the flags/code to disable). The defaults can have appropriate middleware, but the idea is that it is easier to upgrade applications with new Tide versions if I can say I always want a Server without any default middleware and then I add any middleware which "works for me".

jbr commented 4 years ago

Another relevant thing to this conversation: Would anyone actually want to disable cookies? When we talk about "disable all middleware," that currently would include breaking cookie parsing behavior

bluk commented 4 years ago

If I have an API server which does not use cookies, I may not want to have any parsing done for cookies.

Also, if I have a custom session middleware, my concern would be with other middleware potentially interfering with the cookies set. For instance, I want to have private/signed cookies and while there's a PR for that today (which is awesome), there may be requirements which are not met by the API. Then, I would have to always be careful about the cookies or other middleware changing and conflicting with my middleware.

I think having cookie functionality and other default behavior like logging by default is great. Still, as much as I dislike having to choose middleware features (like Express) and just want all the features known to work together (like Rails), I think there are valid use cases where optional functionality is not desired, especially as the framework matures and apps know what they really want.

tirr-c commented 4 years ago

I'd also prefer having none of the middleware applied by default, especially in the nested app scenario, where default middleware would be applied multiple times. Tide could provide some convenience methods to apply middleware that is used often, or let users apply what they need using Server::middleware.

Fishrock123 commented 4 years ago

That's a good point, mounting apps within apps having default middleware issues...

jbr commented 4 years ago

I think the middlewares-running-multiple-times issue could be solved by allowing a middleware to specify that it should only be run once per request and tracking that info on the request. That would also allow for re-entrant routing

Tonyce commented 4 years ago

I think we could remove the build-in middleware,

...
server.middleware(cookies::CookiesMiddleware::new());
server.middleware(log::LogMiddleware::new());
...

we can add the middleware with custom

pbzweihander commented 4 years ago

I think we can offer some helper methods like .with_logger for built-in middlewares.

let mut app = tide::new().with_cookie().with_logger();

It will be more explicit but still easy and friendly.

vladan commented 4 years ago

I think we can offer some helper methods like .with_logger for built-in middlewares.

let mut app = tide::new().with_cookie().with_logger();

Yes! That's in here https://github.com/http-rs/tide/pull/468/files :)

apiraino commented 4 years ago

The "hello world" example pulls 167 crates.

Here's a full list, maybe can it help pointing out other crates that can be feature gated:

Expand list of deps $ cargo clean && cargo build Updating crates.io index Compiling proc-macro2 v1.0.18 Compiling cfg-if v0.1.10 Compiling unicode-xid v0.2.1 Compiling syn v1.0.34 Compiling typenum v1.12.0 Compiling libc v0.2.72 Compiling serde_derive v1.0.114 Compiling version_check v0.9.2 Compiling log v0.4.8 Compiling serde v1.0.114 Compiling lazy_static v1.4.0 Compiling wasm-bindgen-shared v0.2.65 Compiling ryu v1.0.5 Compiling bumpalo v3.4.0 Compiling byteorder v1.3.4 Compiling itoa v0.4.6 Compiling serde_json v1.0.56 Compiling futures-core v0.3.5 Compiling futures-sink v0.3.5 Compiling wasm-bindgen v0.2.65 Compiling pin-project-internal v0.4.22 Compiling getrandom v0.1.14 Compiling memchr v2.3.3 Compiling autocfg v1.0.0 Compiling opaque-debug v0.2.3 Compiling once_cell v1.4.0 Compiling subtle v2.2.3 Compiling pin-utils v0.1.0 Compiling futures-io v0.3.5 Compiling proc-macro-hack v0.5.16 Compiling percent-encoding v2.1.0 Compiling byte-tools v0.3.1 Compiling adler v0.2.3 Compiling tinyvec v0.3.3 Compiling slab v0.4.2 Compiling gimli v0.22.0 Compiling matches v0.1.8 Compiling subtle v1.0.0 Compiling cache-padded v1.1.1 Compiling object v0.20.0 Compiling parking v1.0.5 Compiling rustc-demangle v0.1.16 Compiling waker-fn v1.0.0 Compiling ppv-lite86 v0.2.8 Compiling fake-simd v0.1.2 Compiling anyhow v1.0.31 Compiling fastrand v1.3.3 Compiling maybe-uninit v2.0.0 Compiling scoped-tls v1.0.0 Compiling send_wrapper v0.4.0 Compiling zeroize v1.1.0 Compiling async-task v3.0.0 Compiling dtoa v0.4.6 Compiling data-encoding v2.2.1 Compiling pin-project-lite v0.1.7 Compiling base64 v0.12.3 Compiling infer v0.1.7 Compiling httparse v1.3.4 Compiling stable_deref_trait v1.2.0 Compiling route-recognizer v0.1.13 Compiling standback v0.2.9 Compiling error-chain v0.12.2 Compiling time v0.2.16 Compiling futures-channel v0.3.5 Compiling futures-task v0.3.5 Compiling block-padding v0.1.5 Compiling miniz_oxide v0.4.0 Compiling unicode-bidi v0.3.4 Compiling concurrent-queue v1.1.1 Compiling unicode-normalization v0.1.13 Compiling crossbeam-utils v0.7.2 Compiling kv-log-macro v1.0.7 Compiling idna v0.2.0 Compiling socket2 v0.3.12 Compiling num_cpus v1.13.0 Compiling addr2line v0.13.0 Compiling quote v1.0.7 Compiling rand_core v0.5.1 Compiling generic-array v0.12.3 Compiling url v2.1.1 Compiling backtrace v0.3.50 Compiling rand_chacha v0.2.2 Compiling crossbeam-queue v0.2.3 Compiling universal-hash v0.3.0 Compiling block-cipher-trait v0.6.2 Compiling digest v0.8.1 Compiling crypto-mac v0.7.0 Compiling aead v0.2.0 Compiling block-buffer v0.7.3 Compiling polyval v0.3.3 Compiling byte-pool v0.2.1 Compiling aes-soft v0.3.3 Compiling hmac v0.7.1 Compiling rand v0.7.3 Compiling sha2 v0.8.2 Compiling ghash v0.2.3 Compiling hkdf v0.8.0 Compiling aes v0.3.2 Compiling aes-gcm v0.5.0 Compiling wasm-bindgen-backend v0.2.65 // srsly? Compiling wasm-bindgen-macro-support v0.2.65 Compiling time-macros-impl v0.1.1 Compiling async-attributes v1.1.1 Compiling wasm-bindgen-macro v0.2.65 Compiling time-macros v0.1.0 Compiling pin-project v0.4.22 Compiling futures-util v0.3.5 Compiling cookie v0.14.1 Compiling blocking v0.4.6 Compiling smol v0.1.18 Compiling serde_urlencoded v0.6.1 Compiling serde_qs v0.6.1 Compiling femme v2.1.0 Compiling js-sys v0.3.42 Compiling web-sys v0.3.42 Compiling gloo-timers v0.2.1 Compiling futures-timer v3.0.2 Compiling async-std v1.6.2 Compiling http-types v2.3.0 Compiling async-sse v3.0.0 Compiling async-h1 v2.1.0 Compiling tide v0.11.0 Compiling tide-bloat v0.1.0 (~/tmp/tide-bloat) Finished dev [unoptimized + debuginfo] target(s) in 50.52s
Source code $ cat Cargo.toml src/main.rs -p // cargo.toml [dependencies] tide = "0.11.0" async-std = { version = "1.6.0", features = ["attributes"] } // src/main.rs #[async_std::main] async fn main() -> Result<(), std::io::Error> { let mut app = tide::new(); app.at("/").get(|_| async { Ok("Hello, world!") }); app.listen("127.0.0.1:8080").await?; Ok(()) }
jbr commented 4 years ago

@apiraino Some of the heaviest ones of those are due to https://github.com/async-rs/async-std/issues/823. Please comment on that issue if this matters to you.

apiraino commented 4 years ago

@jbr ah interesting :+1: thanks for pointing me to that issue! I commented here because in my test I had also tried removing tide altogether (basically just compiling asynd-std) and the number of crates went down to 52, so I was tricked into believing that they all were deps related directly by tide :smiley:

mkj commented 4 years ago

Tide needs a way to disable logger at runtime too. If I'm using tide-rustls I can't just disable the logger feature since tide-rustls is including the crate with default features.

Maybe it just needs a Server::set_state() to allow doing Server::new().set_state(the_state).with(other_middleware) ?

jbr commented 4 years ago

this is probably a tide-rustls issue — it should use default-features = false

najamelan commented 3 years ago

An enthusiastic +1 for putting all optional deps behind feature flags. I want to embed an http server in an application. The only thing it has to do is serve static files from one folder on localhost (eg. no tls). When I added tide without default features and with h1-server and ran cargo update, this is what I got in cargo tree:

 ├── tide v0.15.0
│   ├── async-h1 v2.1.4
│   │   ├── async-std v1.7.0
│   │   │   ├── async-global-executor v1.4.3 (*)
│   │   │   ├── async-io v1.2.0 (*)
│   │   │   ├── async-mutex v1.4.0
│   │   │   │   └── event-listener v2.5.1
│   │   │   ├── blocking v1.0.2
│   │   │   │   ├── async-channel v1.5.1
│   │   │   │   │   ├── concurrent-queue v1.2.2 (*)
│   │   │   │   │   ├── event-listener v2.5.1
│   │   │   │   │   └── futures-core v0.3.8
│   │   │   │   ├── async-task v4.0.3
│   │   │   │   ├── atomic-waker v1.0.0
│   │   │   │   ├── fastrand v1.4.0
│   │   │   │   ├── futures-lite v1.11.2 (*)
│   │   │   │   └── once_cell v1.5.2
│   │   │   ├── crossbeam-utils v0.8.0
│   │   │   │   ├── cfg-if v1.0.0
│   │   │   │   ├── const_fn v0.4.3
│   │   │   │   └── lazy_static v1.4.0
│   │   │   │   [build-dependencies]
│   │   │   │   └── autocfg v1.0.1
│   │   │   ├── futures-core v0.3.8
│   │   │   ├── futures-io v0.3.8
│   │   │   ├── futures-lite v1.11.2 (*)
│   │   │   ├── kv-log-macro v1.0.7
│   │   │   │   └── log v0.4.11 (*)
│   │   │   ├── log v0.4.11 (*)
│   │   │   ├── memchr v2.3.4
│   │   │   ├── num_cpus v1.13.0 (*)
│   │   │   ├── once_cell v1.5.2
│   │   │   ├── pin-project-lite v0.1.11
│   │   │   ├── pin-utils v0.1.0
│   │   │   └── slab v0.4.2
│   │   ├── byte-pool v0.2.2
│   │   │   ├── crossbeam-queue v0.2.3
│   │   │   │   ├── cfg-if v0.1.10
│   │   │   │   ├── crossbeam-utils v0.7.2
│   │   │   │   │   ├── cfg-if v0.1.10
│   │   │   │   │   └── lazy_static v1.4.0
│   │   │   │   │   [build-dependencies]
│   │   │   │   │   └── autocfg v1.0.1
│   │   │   │   └── maybe-uninit v2.0.0
│   │   │   └── stable_deref_trait v1.2.0
│   │   ├── futures-core v0.3.8
│   │   ├── http-types v2.8.0
│   │   │   ├── anyhow v1.0.34
│   │   │   ├── async-channel v1.5.1 (*)
│   │   │   ├── async-std v1.7.0 (*)
│   │   │   ├── base64 v0.13.0
│   │   │   ├── cookie v0.14.3
│   │   │   │   ├── aes-gcm v0.8.0
│   │   │   │   │   ├── aead v0.3.2
│   │   │   │   │   │   └── generic-array v0.14.4 (*)
│   │   │   │   │   ├── aes v0.6.0
│   │   │   │   │   │   ├── aes-soft v0.6.4
│   │   │   │   │   │   │   ├── cipher v0.2.5
│   │   │   │   │   │   │   │   └── generic-array v0.14.4 (*)
│   │   │   │   │   │   │   └── opaque-debug v0.3.0
│   │   │   │   │   │   └── cipher v0.2.5 (*)
│   │   │   │   │   ├── cipher v0.2.5 (*)
│   │   │   │   │   ├── ctr v0.6.0
│   │   │   │   │   │   └── cipher v0.2.5 (*)
│   │   │   │   │   ├── ghash v0.3.0
│   │   │   │   │   │   └── polyval v0.4.1
│   │   │   │   │   │       ├── cfg-if v0.1.10
│   │   │   │   │   │       └── universal-hash v0.4.0
│   │   │   │   │   │           ├── generic-array v0.14.4 (*)
│   │   │   │   │   │           └── subtle v2.3.0
│   │   │   │   │   └── subtle v2.3.0
│   │   │   │   ├── base64 v0.12.3
│   │   │   │   ├── hkdf v0.10.0
│   │   │   │   │   ├── digest v0.9.0 (*)
│   │   │   │   │   └── hmac v0.10.1
│   │   │   │   │       ├── crypto-mac v0.10.0
│   │   │   │   │       │   ├── generic-array v0.14.4 (*)
│   │   │   │   │       │   └── subtle v2.3.0
│   │   │   │   │       └── digest v0.9.0 (*)
│   │   │   │   ├── hmac v0.10.1 (*)
│   │   │   │   ├── percent-encoding v2.1.0
│   │   │   │   ├── rand v0.7.3 (*)
│   │   │   │   ├── sha2 v0.9.2
│   │   │   │   │   ├── block-buffer v0.9.0 (*)
│   │   │   │   │   ├── cfg-if v1.0.0
│   │   │   │   │   ├── cpuid-bool v0.1.2
│   │   │   │   │   ├── digest v0.9.0 (*)
│   │   │   │   │   └── opaque-debug v0.3.0
│   │   │   │   └── time v0.2.23
│   │   │   │       ├── const_fn v0.4.3
│   │   │   │       ├── libc v0.2.80
│   │   │   │       ├── standback v0.2.13
│   │   │   │       │   [build-dependencies]
│   │   │   │       │   └── version_check v0.9.2
│   │   │   │       └── time-macros v0.1.1
│   │   │   │           ├── proc-macro-hack v0.5.19
│   │   │   │           └── time-macros-impl v0.1.1
│   │   │   │               ├── proc-macro-hack v0.5.19
│   │   │   │               ├── proc-macro2 v1.0.24 (*)
│   │   │   │               ├── quote v1.0.7 (*)
│   │   │   │               ├── standback v0.2.13 (*)
│   │   │   │               └── syn v1.0.50 (*)
│   │   │   │       [build-dependencies]
│   │   │   │       └── version_check v0.9.2
│   │   │   │   [build-dependencies]
│   │   │   │   └── version_check v0.9.2
│   │   │   ├── futures-lite v1.11.2 (*)
│   │   │   ├── infer v0.2.3
│   │   │   ├── pin-project-lite v0.1.11
│   │   │   ├── rand v0.7.3 (*)
│   │   │   ├── serde v1.0.117 (*)
│   │   │   ├── serde_json v1.0.59
│   │   │   │   ├── itoa v0.4.6
│   │   │   │   ├── ryu v1.0.5
│   │   │   │   └── serde v1.0.117 (*)
│   │   │   ├── serde_qs v0.7.0
│   │   │   │   ├── data-encoding v2.3.1
│   │   │   │   ├── percent-encoding v2.1.0
│   │   │   │   ├── serde v1.0.117 (*)
│   │   │   │   └── thiserror v1.0.22 (*)
│   │   │   ├── serde_urlencoded v0.7.0
│   │   │   │   ├── form_urlencoded v1.0.0 (*)
│   │   │   │   ├── itoa v0.4.6
│   │   │   │   ├── ryu v1.0.5
│   │   │   │   └── serde v1.0.117 (*)
│   │   │   └── url v2.2.0 (*)
│   │   ├── httparse v1.3.4
│   │   ├── lazy_static v1.4.0
│   │   ├── log v0.4.11 (*)
│   │   └── pin-project-lite v0.1.11
│   ├── async-sse v4.1.0
│   │   ├── async-channel v1.5.1 (*)
│   │   ├── async-std v1.7.0 (*)
│   │   ├── http-types v2.8.0 (*)
│   │   ├── log v0.4.11 (*)
│   │   ├── memchr v2.3.4
│   │   └── pin-project-lite v0.1.11
│   ├── async-std v1.7.0 (*)
│   ├── async-trait v0.1.42
│   │   ├── proc-macro2 v1.0.24 (*)
│   │   ├── quote v1.0.7 (*)
│   │   └── syn v1.0.50 (*)
│   ├── futures-util v0.3.8 (*)
│   ├── http-client v6.2.0
│   │   ├── async-trait v0.1.42 (*)
│   │   ├── http-types v2.8.0 (*)
│   │   └── log v0.4.11 (*)
│   ├── http-types v2.8.0 (*)
│   ├── kv-log-macro v1.0.7 (*)
│   ├── log v0.4.11 (*)
│   ├── pin-project-lite v0.1.11
│   ├── route-recognizer v0.2.0
│   ├── serde v1.0.117 (*)
│   └── serde_json v1.0.59 (*)