From ff7cf68461ea8b3f52d6d816d7684ba4723d3042 Mon Sep 17 00:00:00 2001 From: Edgar Onghena Date: Wed, 23 Feb 2022 20:11:28 +0100 Subject: [PATCH] Make HTTP/2 optional via 'http2' feature. Closes #2030. --- core/http/Cargo.toml | 3 ++- core/http/src/tls/listener.rs | 7 ++++++- core/lib/Cargo.toml | 3 ++- core/lib/src/lib.rs | 14 +++++++++++--- core/lib/src/server.rs | 23 +++++++++++++---------- scripts/test.sh | 1 + 6 files changed, 35 insertions(+), 16 deletions(-) diff --git a/core/http/Cargo.toml b/core/http/Cargo.toml index cff33d47..01dbe513 100644 --- a/core/http/Cargo.toml +++ b/core/http/Cargo.toml @@ -18,6 +18,7 @@ edition = "2018" default = [] tls = ["rustls", "tokio-rustls", "rustls-pemfile"] mtls = ["tls", "x509-parser"] +http2 = ["hyper/http2"] private-cookies = ["cookie/private", "cookie/key-expansion"] serde = ["uncased/with-serde-alloc", "serde_"] uuid = ["uuid_"] @@ -50,7 +51,7 @@ optional = true [dependencies.hyper] version = "0.14.9" default-features = false -features = ["http1", "http2", "runtime", "server", "stream"] +features = ["http1", "runtime", "server", "stream"] [dependencies.serde_] package = "serde" diff --git a/core/http/src/tls/listener.rs b/core/http/src/tls/listener.rs index ac65b665..8279985a 100644 --- a/core/http/src/tls/listener.rs +++ b/core/http/src/tls/listener.rs @@ -64,7 +64,12 @@ impl TlsListener { .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("bad TLS config: {}", e)))?; tls_config.ignore_client_order = c.prefer_server_order; - tls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; + + tls_config.alpn_protocols = vec![b"http/1.1".to_vec()]; + if cfg!(feature = "http2") { + tls_config.alpn_protocols.insert(0, b"h2".to_vec()); + } + tls_config.session_storage = ServerSessionMemoryCache::new(1024); tls_config.ticketer = rustls::Ticketer::new() .map_err(|e| io::Error::new(io::ErrorKind::Other, format!("bad TLS ticketer: {}", e)))?; diff --git a/core/lib/Cargo.toml b/core/lib/Cargo.toml index 100e822d..6deb9445 100644 --- a/core/lib/Cargo.toml +++ b/core/lib/Cargo.toml @@ -19,9 +19,10 @@ edition = "2018" all-features = true [features] -default = [] +default = ["http2"] tls = ["rocket_http/tls"] mtls = ["rocket_http/mtls", "tls"] +http2 = ["rocket_http/http2"] secrets = ["rocket_http/private-cookies"] json = ["serde_json", "tokio/io-util"] msgpack = ["rmp-serde", "tokio/io-util"] diff --git a/core/lib/src/lib.rs b/core/lib/src/lib.rs index 1479a40f..8902d8be 100644 --- a/core/lib/src/lib.rs +++ b/core/lib/src/lib.rs @@ -56,25 +56,33 @@ //! //! ## Features //! -//! To avoid compiling unused dependencies, Rocket gates certain features, all -//! of which are disabled by default: +//! To avoid compiling unused dependencies, Rocket gates certain features. With +//! the exception of `http2`, all are disabled by default: //! //! | Feature | Description | //! |-----------|---------------------------------------------------------| //! | `secrets` | Support for authenticated, encrypted [private cookies]. | //! | `tls` | Support for [TLS] encrypted connections. | //! | `mtls` | Support for verified clients via [mutual TLS]. | +//! | `http2` | Support for HTTP/2 (enabled by default). | //! | `json` | Support for [JSON (de)serialization]. | //! | `msgpack` | Support for [MessagePack (de)serialization]. | //! | `uuid` | Support for [UUID value parsing and (de)serialization]. | //! -//! Features can be selectively enabled in `Cargo.toml`: +//! Disabled features can be selectively enabled in `Cargo.toml`: //! //! ```toml //! [dependencies] //! rocket = { version = "0.5.0-rc.1", features = ["secrets", "tls", "json"] } //! ``` //! +//! Conversely, HTTP/2 can be disabled: +//! +//! ```toml +//! [dependencies] +//! rocket = { version = "0.5.0-rc.1", default-features = false } +//! ``` +//! //! [JSON (de)serialization]: crate::serde::json //! [MessagePack (de)serialization]: crate::serde::msgpack //! [UUID value parsing and (de)serialization]: crate::serde::uuid diff --git a/core/lib/src/server.rs b/core/lib/src/server.rs index 6185554b..60ad8e8c 100644 --- a/core/lib/src/server.rs +++ b/core/lib/src/server.rs @@ -405,13 +405,6 @@ impl Rocket { }); } - // Determine keep-alives. - let http1_keepalive = self.config.keep_alive != 0; - let http2_keep_alive = match self.config.keep_alive { - 0 => None, - n => Some(Duration::from_secs(n as u64)) - }; - // Set up cancellable I/O from the given listener. Shutdown occurs when // `Shutdown` (`TripWire`) resolves. This can occur directly through a // notification or indirectly through an external signal which, when @@ -438,6 +431,9 @@ impl Rocket { }); } + // Save the keep-alive value for later use; we're about to move `self`. + let keep_alive = self.config.keep_alive; + // Create the Hyper `Service`. let rocket = Arc::new(self); let service_fn = move |conn: &CancellableIo<_, L::Connection>| { @@ -456,10 +452,17 @@ impl Rocket { // NOTE: `hyper` uses `tokio::spawn()` as the default executor. let listener = CancellableListener::new(shutdown.clone(), listener, grace, mercy); - let server = hyper::Server::builder(Incoming::new(listener)) - .http1_keepalive(http1_keepalive) + let builder = hyper::Server::builder(Incoming::new(listener)); + + #[cfg(feature = "http2")] + let builder = builder.http2_keep_alive_interval(match keep_alive { + 0 => None, + n => Some(Duration::from_secs(n as u64)) + }); + + let server = builder + .http1_keepalive(keep_alive != 0) .http1_preserve_header_case(true) - .http2_keep_alive_interval(http2_keep_alive) .serve(hyper::service::make_service_fn(service_fn)) .with_graceful_shutdown(shutdown.clone()) .map_err(|e| Error::new(ErrorKind::Runtime(Box::new(e)))); diff --git a/scripts/test.sh b/scripts/test.sh index 1e559f73..0ee72fea 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -118,6 +118,7 @@ function test_core() { secrets tls mtls + http2 json msgpack uuid