Merge pull request #136 from junkurihara/fix/keep-original-host

fix: set upstream host in request header by default
This commit is contained in:
Jun Kurihara 2024-01-10 14:50:18 +09:00 committed by GitHub
commit 204a0ef195
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 25 additions and 20 deletions

View file

@ -3,7 +3,7 @@
## 0.7.0 (unreleased) ## 0.7.0 (unreleased)
- Breaking: `hyper`-1.0 for both server and client modules. - Breaking: `hyper`-1.0 for both server and client modules.
- Breaking: Remove `override_host` option in upstream options. Add a reverse option, i.e., `keep_original_host`. That is, `rpxy` always override the host header by the upstream hostname (backend uri host name) by default. If this reverse option specified, original `host` header is maintained or added from the value of url request line. - Breaking: Remove `override_host` option in upstream options. Add a reverse option, i.e., `keep_original_host`, and the similar option `set_upstream_host`. While `keep_original_host` can be explicitly specified, `rpxy` keeps the original `host` given by the incoming request by default. Then, the original `host` header is maintained or added from the value of url request line. If `host` header needs to be overridden with the upstream host name (backend uri's host name), `set_upstream_host` has to be set. If both of `set_upstream_host` and `keep_original_host` are set, `keep_original_host` is prioritized since it is explicitly specified.
- Breaking: Introduced `native-tls-backend` feature to use the native TLS engine to access backend applications. - Breaking: Introduced `native-tls-backend` feature to use the native TLS engine to access backend applications.
- Redesigned: Cache structure is totally redesigned with more memory-efficient way to read from cache file, and more secure way to strongly bind memory-objects with files with hash values. - Redesigned: Cache structure is totally redesigned with more memory-efficient way to read from cache file, and more secure way to strongly bind memory-objects with files with hash values.
- Redesigned: HTTP body handling flow is also redesigned with more memory-and-time efficient techniques without putting the whole objects on memory by using `futures::stream::Stream` and `futures::channel::mpsc` - Redesigned: HTTP body handling flow is also redesigned with more memory-and-time efficient techniques without putting the whole objects on memory by using `futures::stream::Stream` and `futures::channel::mpsc`

View file

@ -57,7 +57,7 @@ upstream = [
] ]
load_balance = "round_robin" # or "random" or "sticky" (sticky session) or "none" (fix to the first one, default) load_balance = "round_robin" # or "random" or "sticky" (sticky session) or "none" (fix to the first one, default)
upstream_options = [ upstream_options = [
"keep_original_host", # do not overwrite HOST value with upstream hostname (like 192.168.xx.x seen from rpxy) "keep_original_host", # [default] do not overwrite HOST value with upstream hostname (like 192.168.xx.x seen from rpxy), which is prior to "set_upstream_host" if both are specified.
"force_http2_upstream", # mutually exclusive with "force_http11_upstream" "force_http2_upstream", # mutually exclusive with "force_http11_upstream"
] ]
@ -76,9 +76,9 @@ upstream = [
] ]
load_balance = "random" # or "round_robin" or "sticky" (sticky session) or "none" (fix to the first one, default) load_balance = "random" # or "round_robin" or "sticky" (sticky session) or "none" (fix to the first one, default)
upstream_options = [ upstream_options = [
"disable_override_host",
"upgrade_insecure_requests", "upgrade_insecure_requests",
"force_http11_upstream", "force_http11_upstream",
"set_upstream_host", # overwrite HOST value with upstream hostname (like www.yahoo.com)
] ]
###################################################################### ######################################################################

View file

@ -1,6 +1,6 @@
[package] [package]
name = "rpxy" name = "rpxy"
version = "0.7.0-alpha.0" version = "0.7.0-alpha.1"
authors = ["Jun Kurihara"] authors = ["Jun Kurihara"]
homepage = "https://github.com/junkurihara/rust-rpxy" homepage = "https://github.com/junkurihara/rust-rpxy"
repository = "https://github.com/junkurihara/rust-rpxy" repository = "https://github.com/junkurihara/rust-rpxy"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "rpxy-lib" name = "rpxy-lib"
version = "0.7.0-alpha.0" version = "0.7.0-alpha.1"
authors = ["Jun Kurihara"] authors = ["Jun Kurihara"]
homepage = "https://github.com/junkurihara/rust-rpxy" homepage = "https://github.com/junkurihara/rust-rpxy"
repository = "https://github.com/junkurihara/rust-rpxy" repository = "https://github.com/junkurihara/rust-rpxy"

View file

@ -1,10 +1,17 @@
use crate::error::*; use crate::error::*;
/// Options for request message to be sent to upstream.
#[derive(Debug, Clone, Hash, Eq, PartialEq)] #[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub enum UpstreamOption { pub enum UpstreamOption {
/// Keep original host header, which is prioritized over SetUpstreamHost
KeepOriginalHost, KeepOriginalHost,
/// Overwrite host header with upstream hostname
SetUpstreamHost,
/// Add upgrade-insecure-requests header
UpgradeInsecureRequests, UpgradeInsecureRequests,
/// Force HTTP/1.1 upstream
ForceHttp11Upstream, ForceHttp11Upstream,
/// Force HTTP/2 upstream
ForceHttp2Upstream, ForceHttp2Upstream,
// TODO: Adds more options for heder override // TODO: Adds more options for heder override
} }
@ -13,6 +20,7 @@ impl TryFrom<&str> for UpstreamOption {
fn try_from(val: &str) -> RpxyResult<Self> { fn try_from(val: &str) -> RpxyResult<Self> {
match val { match val {
"keep_original_host" => Ok(Self::KeepOriginalHost), "keep_original_host" => Ok(Self::KeepOriginalHost),
"set_upstream_host" => Ok(Self::SetUpstreamHost),
"upgrade_insecure_requests" => Ok(Self::UpgradeInsecureRequests), "upgrade_insecure_requests" => Ok(Self::UpgradeInsecureRequests),
"force_http11_upstream" => Ok(Self::ForceHttp11Upstream), "force_http11_upstream" => Ok(Self::ForceHttp11Upstream),
"force_http2_upstream" => Ok(Self::ForceHttp2Upstream), "force_http2_upstream" => Ok(Self::ForceHttp2Upstream),

View file

@ -99,14 +99,14 @@ where
headers.insert(header::TE, HeaderValue::from_bytes("trailers".as_bytes()).unwrap()); headers.insert(header::TE, HeaderValue::from_bytes("trailers".as_bytes()).unwrap());
} }
// add "host" header of original server_name if not exist (default) // by default, add "host" header of original server_name if not exist
if req.headers().get(header::HOST).is_none() { if req.headers().get(header::HOST).is_none() {
let org_host = req.uri().host().ok_or_else(|| anyhow!("Invalid request"))?.to_owned(); let org_host = req.uri().host().ok_or_else(|| anyhow!("Invalid request"))?.to_owned();
req req
.headers_mut() .headers_mut()
.insert(header::HOST, HeaderValue::from_str(&org_host)?); .insert(header::HOST, HeaderValue::from_str(&org_host)?);
}; };
let original_host_header = req.headers().get(header::HOST).unwrap().clone(); println!("{:?}", req.headers().get(header::HOST));
///////////////////////////////////////////// /////////////////////////////////////////////
// Fix unique upstream destination since there could be multiple ones. // Fix unique upstream destination since there could be multiple ones.
@ -133,10 +133,8 @@ where
// apply upstream-specific headers given in upstream_option // apply upstream-specific headers given in upstream_option
let headers = req.headers_mut(); let headers = req.headers_mut();
// by default, host header is overwritten with upstream hostname
override_host_header(headers, &upstream_chosen.uri)?;
// apply upstream options to header // apply upstream options to header
apply_upstream_options_to_header(headers, &original_host_header, upstream_candidates)?; apply_upstream_options_to_header(headers, &upstream_chosen.uri, upstream_candidates)?;
// update uri in request // update uri in request
ensure!( ensure!(
@ -182,7 +180,6 @@ where
update_request_line(req, upstream_chosen, upstream_candidates)?; update_request_line(req, upstream_chosen, upstream_candidates)?;
} }
Ok(context) Ok(context)
} }
} }

View file

@ -86,8 +86,8 @@ pub(super) fn set_sticky_cookie_lb_context(
Ok(()) Ok(())
} }
/// default: overwrite HOST value with upstream hostname (like 192.168.xx.x seen from rpxy) /// overwrite HOST value with upstream hostname (like 192.168.xx.x seen from rpxy)
pub(super) fn override_host_header(headers: &mut HeaderMap, upstream_base_uri: &Uri) -> Result<()> { fn override_host_header(headers: &mut HeaderMap, upstream_base_uri: &Uri) -> Result<()> {
let mut upstream_host = upstream_base_uri let mut upstream_host = upstream_base_uri
.host() .host()
.ok_or_else(|| anyhow!("No hostname is given"))? .ok_or_else(|| anyhow!("No hostname is given"))?
@ -105,18 +105,18 @@ pub(super) fn override_host_header(headers: &mut HeaderMap, upstream_base_uri: &
/// Apply options to request header, which are specified in the configuration /// Apply options to request header, which are specified in the configuration
pub(super) fn apply_upstream_options_to_header( pub(super) fn apply_upstream_options_to_header(
headers: &mut HeaderMap, headers: &mut HeaderMap,
original_host_header: &HeaderValue, upstream_base_uri: &Uri,
// _client_addr: &SocketAddr, // _client_addr: &SocketAddr,
upstream: &UpstreamCandidates, upstream: &UpstreamCandidates,
// _upstream_base_uri: &Uri,
) -> Result<()> { ) -> Result<()> {
for opt in upstream.options.iter() { for opt in upstream.options.iter() {
match opt { match opt {
UpstreamOption::KeepOriginalHost => { UpstreamOption::SetUpstreamHost => {
// revert hostname // prioritize KeepOriginalHost
headers if !upstream.options.contains(&UpstreamOption::KeepOriginalHost) {
.insert(header::HOST, original_host_header.to_owned()) // overwrite host header, this removes all the HOST header values
.ok_or_else(|| anyhow!("Failed to revert host header in keep_original_host option"))?; override_host_header(headers, upstream_base_uri)?;
}
} }
UpstreamOption::UpgradeInsecureRequests => { UpstreamOption::UpgradeInsecureRequests => {
// add upgrade-insecure-requests in request header if not exist // add upgrade-insecure-requests in request header if not exist