diff --git a/Cargo.lock b/Cargo.lock index c2afffa..cbf137b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,6 +128,33 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "aws-lc-rs" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae74d9bd0a7530e8afd1770739ad34b36838829d6ad61818f9230f683f5ad77" +dependencies = [ + "aws-lc-sys", + "mirai-annotations", + "paste", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0e249228c6ad2d240c2dc94b714d711629d52bad946075d8e9b2f5391f0703" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", +] + [[package]] name = "backtrace" version = "0.3.71" @@ -173,6 +200,29 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.5.0", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.64", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -238,6 +288,11 @@ name = "cc" version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] [[package]] name = "certain-map" @@ -260,6 +315,15 @@ dependencies = [ "syn 2.0.64", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -281,6 +345,17 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.5.4" @@ -321,6 +396,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.1" @@ -520,6 +604,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + [[package]] name = "dyn-clone" version = "1.0.17" @@ -690,6 +780,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.30" @@ -818,6 +914,12 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "group" version = "0.13.0" @@ -915,6 +1017,15 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "http" version = "0.2.12" @@ -1024,7 +1135,7 @@ dependencies = [ "futures-util", "http 0.2.12", "hyper 0.14.28", - "rustls", + "rustls 0.21.12", "tokio", "tokio-rustls", ] @@ -1145,6 +1256,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -1163,12 +1283,28 @@ dependencies = [ "spin 0.5.2", ] +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.52.5", +] + [[package]] name = "libm" version = "0.2.8" @@ -1244,6 +1380,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1265,6 +1407,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mirai-annotations" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" + [[package]] name = "monoio" version = "0.2.3" @@ -1332,7 +1480,7 @@ dependencies = [ "monoio", "monoio-codec", "monoio-compat", - "monoio-rustls", + "monoio-rustls 0.3.0", "service-async", "slab", "smallvec", @@ -1382,7 +1530,20 @@ dependencies = [ "bytes", "monoio", "monoio-io-wrapper", - "rustls", + "rustls 0.21.12", + "thiserror", +] + +[[package]] +name = "monoio-rustls" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e31f422825bd7fb19957af6eaf89d7234ba143fcc0e515f5a2f526e332d1875" +dependencies = [ + "bytes", + "monoio", + "monoio-io-wrapper", + "rustls 0.23.12", "thiserror", ] @@ -1404,9 +1565,9 @@ dependencies = [ [[package]] name = "monoio-transports" -version = "0.4.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89949adbb3aec3bbe978a50f6205dd9e9c67ad4f4ee87fa8a88bc85bfa30fde9" +checksum = "e219624bc3f0c9ec5a6bbc5dbc514cb718b2cf19a1ccdc78bf6c43d5048fa639" dependencies = [ "bytes", "http 1.1.0", @@ -1415,15 +1576,15 @@ dependencies = [ "monoio-codec", "monoio-compat", "monoio-http", - "monoio-rustls", - "rustls", + "monoio-rustls 0.4.0", + "rustls 0.23.12", "serde", "serde_json", "service-async", "smol_str", "thiserror", "tracing", - "webpki-roots", + "webpki-roots 0.26.3", ] [[package]] @@ -1487,7 +1648,7 @@ dependencies = [ "monoio-compat", "monoio-http", "monoio-native-tls", - "monoio-rustls", + "monoio-rustls 0.3.0", "monoio-thrift", "monoio-transports", "monolake-core", @@ -1496,14 +1657,14 @@ dependencies = [ "pin-project-lite", "proxy-protocol", "rand", - "rustls", + "rustls 0.21.12", "rustls-pemfile", "serde", "service-async", "thiserror", "tracing", "url", - "webpki-roots", + "webpki-roots 0.25.4", ] [[package]] @@ -1546,6 +1707,16 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1806,6 +1977,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da24af13fd75465e54b0040b7303173dc90d5f53a82ead2041f8ad453678247" +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -1898,6 +2075,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.64", +] + [[package]] name = "primeorder" version = "0.13.6" @@ -2041,7 +2228,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", + "rustls 0.21.12", "rustls-pemfile", "serde", "serde_json", @@ -2055,7 +2242,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.25.4", "winreg", ] @@ -2116,6 +2303,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -2146,10 +2339,25 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.102.6", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -2159,6 +2367,12 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -2169,6 +2383,18 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.18" @@ -2383,6 +2609,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signature" version = "2.2.0" @@ -2652,7 +2884,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.12", "tokio", ] @@ -2976,6 +3208,27 @@ version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3179,3 +3432,17 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.64", +] diff --git a/Cargo.toml b/Cargo.toml index 3a6ab5d..77629ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ monoio = "0.2.2" monoio-codec = "0.3" monoio-http = "0.3.5" monoio-thrift = "0.1.1" -monoio-transports = "0.4.2" +monoio-transports = "0.5.0" monoio-native-tls = "0.3.0" monoio-rustls = "0.3.0" native-tls = "0.2" diff --git a/examples/config.toml b/examples/config.toml index 482301e..9427bae 100644 --- a/examples/config.toml +++ b/examples/config.toml @@ -9,6 +9,7 @@ listener = { type = "socket", value = "0.0.0.0:8080" } [[servers.demo_basic.routes]] path = '/' +protocol = "http2 upstreams = [{ endpoint = { type = "uri", value = "https://www.bytedance.com/" } }] [[servers.demo_basic.routes]] diff --git a/monolake-services/src/http/handlers/connection_persistence.rs b/monolake-services/src/http/handlers/connection_persistence.rs index 102dc44..dd4c075 100644 --- a/monolake-services/src/http/handlers/connection_persistence.rs +++ b/monolake-services/src/http/handlers/connection_persistence.rs @@ -52,7 +52,10 @@ //! //! let config = DummyConfig; //! let stacks = FactoryStack::new(config) -//! .replace(UpstreamHandler::factory(Default::default())) +//! .replace(UpstreamHandler::factory( +//! Default::default(), +//! Default::default(), +//! )) //! .push(ContentHandler::layer()) //! .push(RewriteAndRouteHandler::layer()) //! .push(ConnectionReuseHandler::layer()) diff --git a/monolake-services/src/http/handlers/content_handler.rs b/monolake-services/src/http/handlers/content_handler.rs index 67ba41c..79303fe 100644 --- a/monolake-services/src/http/handlers/content_handler.rs +++ b/monolake-services/src/http/handlers/content_handler.rs @@ -52,7 +52,10 @@ //! //! let config = DummyConfig; //! let stacks = FactoryStack::new(config) -//! .replace(UpstreamHandler::factory(Default::default())) +//! .replace(UpstreamHandler::factory( +//! Default::default(), +//! Default::default(), +//! )) //! .push(ContentHandler::layer()) //! .push(RewriteAndRouteHandler::layer()) //! .push(ConnectionReuseHandler::layer()) diff --git a/monolake-services/src/http/handlers/mod.rs b/monolake-services/src/http/handlers/mod.rs index 0a13e68..6a47b3c 100644 --- a/monolake-services/src/http/handlers/mod.rs +++ b/monolake-services/src/http/handlers/mod.rs @@ -88,7 +88,10 @@ //! //! let config = DummyConfig; //! let stacks = FactoryStack::new(config) -//! .replace(UpstreamHandler::factory(Default::default())) +//! .replace(UpstreamHandler::factory( +//! Default::default(), +//! Default::default(), +//! )) //! .push(ContentHandler::layer()) //! .push(RewriteAndRouteHandler::layer()) //! .push(ConnectionReuseHandler::layer()) diff --git a/monolake-services/src/http/handlers/route.rs b/monolake-services/src/http/handlers/route.rs index 9aa4a80..b945c40 100644 --- a/monolake-services/src/http/handlers/route.rs +++ b/monolake-services/src/http/handlers/route.rs @@ -59,7 +59,10 @@ //! //! let config = DummyConfig; //! let stacks = FactoryStack::new(config) -//! .replace(UpstreamHandler::factory(Default::default())) +//! .replace(UpstreamHandler::factory( +//! Default::default(), +//! Default::default(), +//! )) //! .push(ContentHandler::layer()) //! .push(RewriteAndRouteHandler::layer()) //! .push(ConnectionReuseHandler::layer()) @@ -94,7 +97,7 @@ //! - Support for more advanced routing patterns (e.g., regex-based routing). //! - Enhanced metrics and logging for better observability. //! - Integration with service discovery systems for dynamic upstream management. -use http::{uri::Scheme, HeaderValue, Request, StatusCode, Version}; +use http::{uri::Scheme, HeaderValue, Request, StatusCode}; use matchit::Router; use monoio_http::common::body::FixedBody; use monolake_core::{ @@ -322,12 +325,6 @@ pub struct Upstream { /// If not specified, it defaults to a value provided by the `default_weight` function. #[serde(default = "default_weight")] pub weight: u16, - - /// The HTTP version to use when communicating with this upstream. - /// - /// If not specified, it defaults to the value provided by `HttpVersion::default`. - #[serde(default = "HttpVersion::default")] - pub version: HttpVersion, } /// Represents different types of endpoints for upstream servers. @@ -372,9 +369,6 @@ fn rewrite_request(request: &mut Request, upstream: &Upstream) { _ => unimplemented!("not implement"), }; - let endpoint_version = upstream.version.convert_to_http_version(); - *request.version_mut() = endpoint_version; - if let Some(authority) = remote.authority() { let header_value = HeaderValue::from_str(authority.as_str()).unwrap_or(HeaderValue::from_static("")); @@ -384,19 +378,11 @@ fn rewrite_request(request: &mut Request, upstream: &Upstream) { header_value ); - match endpoint_version { - Version::HTTP_11 => request.headers_mut().remove(http::header::HOST), - Version::HTTP_2 => request.headers_mut().remove(http::header::HOST), - _ => unimplemented!(), - }; + request.headers_mut().remove(http::header::HOST); - if upstream.version.convert_to_http_version() == Version::HTTP_2 { - request.headers_mut().remove(http::header::HOST); - } else { - request - .headers_mut() - .insert(http::header::HOST, header_value); - } + request + .headers_mut() + .insert(http::header::HOST, header_value); let scheme = match remote.scheme() { Some(scheme) => scheme.to_owned(), @@ -448,7 +434,6 @@ mod tests { upstreams: Vec::from([Upstream { endpoint: Endpoint::Uri(format!("http://test{n}.endpoint").parse().unwrap()), weight: Default::default(), - version: HttpVersion::HTTP1_1, }]), }) } diff --git a/monolake-services/src/http/handlers/upstream.rs b/monolake-services/src/http/handlers/upstream.rs index f1830e1..bde1df2 100644 --- a/monolake-services/src/http/handlers/upstream.rs +++ b/monolake-services/src/http/handlers/upstream.rs @@ -63,7 +63,7 @@ use monoio_http::common::{ use monoio_transports::connectors::{TlsConnector, TlsStream}; use monoio_transports::{ connectors::{Connector, TcpConnector}, - http::H1Connector, + http::{HttpConnection, HttpConnector}, }; use monolake_core::{ context::{PeerAddr, RemoteAddr}, @@ -73,11 +73,11 @@ use monolake_core::{ use service_async::{AsyncMakeService, MakeService, ParamMaybeRef, ParamRef, Service}; use tracing::{debug, info}; -use crate::http::generate_response; +use crate::http::{generate_response, Protocol}; -type HttpConnector = H1Connector; +type PooledHttpConnector = HttpConnector; #[cfg(feature = "tls")] -type HttpsConnector = H1Connector< +type PooledHttpsConnector = HttpConnector< TlsConnector, monoio_transports::connectors::TcpTlsAddr, TlsStream, @@ -91,25 +91,14 @@ type HttpsConnector = H1Connector< /// /// For implementation details and example usage, see the /// [module level documentation](crate::http::handlers::upstream). -#[derive(Clone)] +#[derive(Default)] pub struct UpstreamHandler { - connector: HttpConnector, + http_connector: PooledHttpConnector, #[cfg(feature = "tls")] - tls_connector: HttpsConnector, + https_connector: PooledHttpsConnector, pub http_upstream_timeout: HttpUpstreamTimeout, } -impl Default for UpstreamHandler { - fn default() -> Self { - Self { - connector: HttpConnector::default().with_default_pool(), - #[cfg(feature = "tls")] - tls_connector: HttpsConnector::default().with_default_pool(), - http_upstream_timeout: Default::default(), - } - } -} - impl UpstreamHandler { #[cfg(not(feature = "tls"))] pub fn new(connector: HttpConnector) -> Self { @@ -120,17 +109,21 @@ impl UpstreamHandler { } #[cfg(feature = "tls")] - pub fn new(connector: HttpConnector, tls_connector: HttpsConnector) -> Self { + pub fn new(connector: PooledHttpConnector, tls_connector: PooledHttpsConnector) -> Self { UpstreamHandler { - connector, - tls_connector, + http_connector: connector, + https_connector: tls_connector, http_upstream_timeout: Default::default(), } } - pub const fn factory(http_upstream_timeout: HttpUpstreamTimeout) -> UpstreamHandlerFactory { + pub const fn factory( + http_upstream_timeout: HttpUpstreamTimeout, + protocol: Protocol, + ) -> UpstreamHandlerFactory { UpstreamHandlerFactory { http_upstream_timeout, + protocol, } } } @@ -138,7 +131,8 @@ impl UpstreamHandler { impl Service<(Request, CX)> for UpstreamHandler where CX: ParamRef + ParamMaybeRef>, - B: Body, + // B: Body, + B: Body, HttpError: From, { type Response = ResponseWithContinue; @@ -157,10 +151,10 @@ where impl UpstreamHandler { async fn send_http_request( &self, - req: Request, + mut req: Request, ) -> Result, Infallible> where - B: Body, + B: Body, HttpError: From, { let Some(host) = req.uri().host() else { @@ -180,8 +174,19 @@ impl UpstreamHandler { return Ok((generate_response(StatusCode::BAD_REQUEST, true), true)); }; debug!("key: {:?}", key); - let mut conn = match self.connector.connect(key).await { - Ok(conn) => conn, + let mut conn = match self.http_connector.connect(key).await { + Ok(conn) => { + match &conn { + HttpConnection::Http1(_) => { + *req.version_mut() = http::Version::HTTP_11; + } + HttpConnection::Http2(_) => { + *req.version_mut() = http::Version::HTTP_2; + req.headers_mut().remove(http::header::HOST); + } + } + conn + } Err(e) => { info!("connect upstream error: {:?}", e); return Ok((generate_response(StatusCode::BAD_GATEWAY, true), true)); @@ -202,7 +207,7 @@ impl UpstreamHandler { req: Request, ) -> Result, Infallible> where - B: Body, + B: Body, HttpError: From, { let key = match req.uri().try_into() { @@ -215,7 +220,8 @@ impl UpstreamHandler { debug!("key: {:?}", key); let connect = match self.http_upstream_timeout.connect_timeout { Some(connect_timeout) => { - match monoio::time::timeout(connect_timeout, self.tls_connector.connect(key)).await + match monoio::time::timeout(connect_timeout, self.https_connector.connect(key)) + .await { Ok(x) => x, Err(_) => { @@ -224,7 +230,7 @@ impl UpstreamHandler { } } } - None => self.tls_connector.connect(key).await, + None => self.https_connector.connect(key).await, }; let mut conn = match connect { @@ -246,12 +252,17 @@ impl UpstreamHandler { pub struct UpstreamHandlerFactory { http_upstream_timeout: HttpUpstreamTimeout, + protocol: Protocol, } impl UpstreamHandlerFactory { - pub fn new(http_upstream_timeout: HttpUpstreamTimeout) -> UpstreamHandlerFactory { + pub fn new( + http_upstream_timeout: HttpUpstreamTimeout, + protocol: Protocol, + ) -> UpstreamHandlerFactory { UpstreamHandlerFactory { http_upstream_timeout, + protocol, } } } @@ -262,11 +273,38 @@ impl MakeService for UpstreamHandlerFactory { type Error = Infallible; fn make_via_ref(&self, _old: Option<&Self::Service>) -> Result { - let http_connector = HttpConnector::default().with_default_pool(); + let http_connector = match self.protocol { + Protocol::HTTP2 => PooledHttpConnector::build_tcp_http2_only(), + Protocol::HTTP11 => { + // No support for upgrades to HTTP/2 + PooledHttpConnector::build_tcp_http1_only() + } + Protocol::Auto => { + // Default to HTTP/1.1 + PooledHttpConnector::default() + } + }; + + #[cfg(feature = "tls")] + let https_connector = match self.protocol { + Protocol::HTTP2 => { + // ALPN advertised with h2 + PooledHttpsConnector::build_tls_http2_only() + } + Protocol::HTTP11 => { + // ALPN advertised with http1.1 + PooledHttpsConnector::build_tls_http1_only() + } + Protocol::Auto => { + // ALPN advertised with h2/http1.1 + PooledHttpsConnector::default() + } + }; + Ok(UpstreamHandler { - connector: http_connector, + http_connector, #[cfg(feature = "tls")] - tls_connector: HttpsConnector::default().with_default_pool(), + https_connector, http_upstream_timeout: self.http_upstream_timeout, }) } @@ -280,11 +318,11 @@ impl AsyncMakeService for UpstreamHandlerFactory { &self, _old: Option<&Self::Service>, ) -> Result { - let http_connector = HttpConnector::default().with_default_pool(); + let http_connector = PooledHttpConnector::default(); Ok(UpstreamHandler { - connector: http_connector, + http_connector, #[cfg(feature = "tls")] - tls_connector: HttpsConnector::default().with_default_pool(), + https_connector: PooledHttpsConnector::default(), http_upstream_timeout: self.http_upstream_timeout, }) } diff --git a/monolake-services/src/http/mod.rs b/monolake-services/src/http/mod.rs index 54d6618..0325131 100644 --- a/monolake-services/src/http/mod.rs +++ b/monolake-services/src/http/mod.rs @@ -42,6 +42,7 @@ //! - The modular design allows for easy extension and customization of HTTP handling behavior //! - Custom handlers can be implemented and integrated into the `HttpCoreService` use http::HeaderValue; +use serde::{Deserialize, Serialize}; pub use self::core::{HttpCoreService, HttpServerTimeout}; pub mod handlers; @@ -57,3 +58,12 @@ pub(crate) const CLOSE_VALUE: HeaderValue = HeaderValue::from_static(CLOSE); #[allow(clippy::declare_interior_mutable_const)] pub(crate) const KEEPALIVE_VALUE: HeaderValue = HeaderValue::from_static(KEEPALIVE); pub(crate) use util::generate_response; + +#[derive(Debug, Copy, Clone, Default, Deserialize, Serialize)] +#[serde(tag = "type", content = "value", rename_all = "snake_case")] +pub enum Protocol { + HTTP2, + HTTP11, + #[default] + Auto, +} diff --git a/monolake/src/config/extractor.rs b/monolake/src/config/extractor.rs index 6666fbe..00aacb6 100644 --- a/monolake/src/config/extractor.rs +++ b/monolake/src/config/extractor.rs @@ -1,7 +1,10 @@ use certain_map::Param; #[cfg(feature = "openid")] use monolake_services::http::handlers::openid::OpenIdConfig; -use monolake_services::{http::HttpServerTimeout, thrift::ttheader::ThriftServerTimeout}; +use monolake_services::{ + http::{HttpServerTimeout, Protocol}, + thrift::ttheader::ThriftServerTimeout, +}; use super::{RouteConfig, ServerConfig}; @@ -38,3 +41,10 @@ impl Param for ServerConfig { self.tls.clone() } } + +impl Param for ServerConfig { + #[inline] + fn param(&self) -> Protocol { + self.protocol + } +} diff --git a/monolake/src/config/mod.rs b/monolake/src/config/mod.rs index b6a4142..c9834fa 100644 --- a/monolake/src/config/mod.rs +++ b/monolake/src/config/mod.rs @@ -5,7 +5,7 @@ use monolake_core::{ listener::ListenerBuilder, }; use monolake_services::{ - http::{handlers::route::RouteConfig, HttpServerTimeout}, + http::{handlers::route::RouteConfig, HttpServerTimeout, Protocol}, thrift::ttheader::ThriftServerTimeout, }; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -35,6 +35,7 @@ pub struct ServerConfig { pub tls: monolake_services::tls::TlsConfig, pub routes: Vec, pub http_server_timeout: HttpServerTimeout, + pub protocol: Protocol, pub thrift_server_timeout: ThriftServerTimeout, #[cfg(feature = "openid")] pub auth_config: Option, @@ -48,6 +49,8 @@ pub struct ServerUserConfig { pub tls: Option, pub routes: Vec, pub http_timeout: Option, + #[serde(default = "Protocol::default")] + pub protocol: Protocol, pub thrift_timeout: Option, } @@ -174,6 +177,7 @@ impl Config { .server_message_timeout_sec .map(Duration::from_secs), }, + protocol: server.protocol, #[cfg(feature = "openid")] auth_config: None, }, diff --git a/monolake/src/factory.rs b/monolake/src/factory.rs index 257e0d6..b2fea2c 100644 --- a/monolake/src/factory.rs +++ b/monolake/src/factory.rs @@ -16,6 +16,7 @@ use monolake_services::{ handlers::{ ConnectionReuseHandler, ContentHandler, RewriteAndRouteHandler, UpstreamHandler, }, + Protocol, }, tcp::Accept, thrift::{handlers::ProxyHandler as TProxyHandler, ttheader::TtheaderCoreService}, @@ -39,8 +40,9 @@ pub fn l7_factory( > { match config.proxy_type { crate::config::ProxyType::Http => { + let protocol: Protocol = config.param(); let stacks = FactoryStack::new(config.clone()) - .replace(UpstreamHandler::factory(Default::default())) + .replace(UpstreamHandler::factory(Default::default(), protocol)) .push(ContentHandler::layer()) .push(RewriteAndRouteHandler::layer());