diff --git a/rpxy-lib/src/backend/upstream_opts.rs b/rpxy-lib/src/backend/upstream_opts.rs index 1cdb2a5..a96bb58 100644 --- a/rpxy-lib/src/backend/upstream_opts.rs +++ b/rpxy-lib/src/backend/upstream_opts.rs @@ -4,8 +4,8 @@ use crate::error::*; pub enum UpstreamOption { OverrideHost, UpgradeInsecureRequests, - ConvertHttpsTo11, - ConvertHttpsTo2, + ForceHttp11Upstream, + ForceHttp2Upstream, // TODO: Adds more options for heder override } impl TryFrom<&str> for UpstreamOption { @@ -14,8 +14,8 @@ impl TryFrom<&str> for UpstreamOption { match val { "override_host" => Ok(Self::OverrideHost), "upgrade_insecure_requests" => Ok(Self::UpgradeInsecureRequests), - "convert_https_to_11" => Ok(Self::ConvertHttpsTo11), - "convert_https_to_2" => Ok(Self::ConvertHttpsTo2), + "force_http11_upstream" => Ok(Self::ForceHttp11Upstream), + "force_http2_upstream" => Ok(Self::ForceHttp2Upstream), _ => Err(RpxyError::Other(anyhow!("Unsupported header option"))), } } diff --git a/rpxy-lib/src/globals.rs b/rpxy-lib/src/globals.rs index 6186d84..0bed623 100644 --- a/rpxy-lib/src/globals.rs +++ b/rpxy-lib/src/globals.rs @@ -225,7 +225,8 @@ where } if !(upstream.iter().all(|(_, elem)| { - !(elem.opts.contains(&UpstreamOption::ConvertHttpsTo11) && elem.opts.contains(&UpstreamOption::ConvertHttpsTo2)) + !(elem.opts.contains(&UpstreamOption::ForceHttp11Upstream) + && elem.opts.contains(&UpstreamOption::ForceHttp2Upstream)) })) { error!("Either one of force_http11 or force_http2 can be enabled"); return Err(RpxyError::ConfigBuild("Invalid upstream option setting")); diff --git a/rpxy-lib/src/handler/handler_main.rs b/rpxy-lib/src/handler/handler_main.rs index 0b554ae..bb5b22e 100644 --- a/rpxy-lib/src/handler/handler_main.rs +++ b/rpxy-lib/src/handler/handler_main.rs @@ -356,14 +356,20 @@ where } // If not specified (force_httpXX_upstream) and https, version is preserved except for http/3 - apply_upstream_options_to_request_line(req, upstream_group)?; - // Maybe workaround: Change version to http/1.1 when destination scheme is http - if req.version() != Version::HTTP_11 && upstream_chosen.uri.scheme() == Some(&Scheme::HTTP) { - *req.version_mut() = Version::HTTP_11; - } else if req.version() == Version::HTTP_3 { - debug!("HTTP/3 is currently unsupported for request to upstream. Use HTTP/2."); - *req.version_mut() = Version::HTTP_2; + match req.version() { + Version::HTTP_3 => { + debug!("HTTP/3 is currently unsupported for request to upstream."); + *req.version_mut() = Version::HTTP_2; + } + _ => { + if upstream_chosen.uri.scheme() == Some(&Scheme::HTTP) { + // Change version to http/1.1 when destination scheme is http + debug!("Change version to http/1.1 when destination scheme is http."); + *req.version_mut() = Version::HTTP_11; + } + } } + apply_upstream_options_to_request_line(req, upstream_group)?; Ok(context) } diff --git a/rpxy-lib/src/handler/utils_request.rs b/rpxy-lib/src/handler/utils_request.rs index 03e36a1..6204f41 100644 --- a/rpxy-lib/src/handler/utils_request.rs +++ b/rpxy-lib/src/handler/utils_request.rs @@ -11,8 +11,12 @@ use hyper::{header, Request}; pub(super) fn apply_upstream_options_to_request_line(req: &mut Request, upstream: &UpstreamGroup) -> Result<()> { for opt in upstream.opts.iter() { match opt { - UpstreamOption::ConvertHttpsTo11 => *req.version_mut() = hyper::Version::HTTP_11, - UpstreamOption::ConvertHttpsTo2 => *req.version_mut() = hyper::Version::HTTP_2, + UpstreamOption::ForceHttp11Upstream => *req.version_mut() = hyper::Version::HTTP_11, + UpstreamOption::ForceHttp2Upstream => { + // case: h2c -> https://www.rfc-editor.org/rfc/rfc9113.txt + // Upgrade from HTTP/1.1 to HTTP/2 is deprecated. So, http-2 prior knowledge is required. + *req.version_mut() = hyper::Version::HTTP_2; + } _ => (), } } diff --git a/rpxy-lib/src/lib.rs b/rpxy-lib/src/lib.rs index c472b05..b2a777c 100644 --- a/rpxy-lib/src/lib.rs +++ b/rpxy-lib/src/lib.rs @@ -70,6 +70,7 @@ where .enable_http2() .build(); + // TODO: HTTP2 only client is needed for http2 cleartext case let msg_handler = HttpMessageHandlerBuilder::default() .forwarder(Arc::new(Client::builder().build::<_, hyper::Body>(connector))) .globals(globals.clone())