Skip to content

Commit

Permalink
http: send both forwarded and x-forwarded-for headers by default
Browse files Browse the repository at this point in the history
  • Loading branch information
picoHz committed Nov 7, 2024
1 parent 288d5be commit 64711a4
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 41 deletions.
55 changes: 25 additions & 30 deletions taxy/src/proxy/http/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use std::{iter, net::IpAddr};
#[derive(Default, Debug)]
pub struct HeaderRewriter {
trust_upstream_headers: bool,
use_std_forwarded: bool,
set_via: Option<HeaderValue>,
}

Expand Down Expand Up @@ -85,30 +84,25 @@ impl HeaderRewriter {
self.remove_untrusted_headers(headers);
}

headers.insert(
"x-forwarded-proto",
HeaderValue::from_static(forwarded_proto),
);
if forwarded.is_empty() {
forwarded = x_forwarded_for
.iter()
.map(|ip| forwarded_for_directive(*ip))
.collect();
}
if let Ok(forwarded_value) = HeaderValue::from_str(
&forwarded
.into_iter()
.chain(iter::once(forwarded_for_directive(remote_addr)))
.chain(header_host.map(|host| forwarded_host_directive(&host)))
.chain(iter::once(forwarded_proto_directive(forwarded_proto)))
.collect::<Vec<_>>()
.join(", "),
) {
headers.insert(FORWARDED, forwarded_value);
}

if self.use_std_forwarded || !forwarded.is_empty() {
if forwarded.is_empty() {
forwarded = x_forwarded_for
.into_iter()
.map(forwarded_for_directive)
.collect();
}
if let Ok(forwarded_value) = HeaderValue::from_str(
&forwarded
.into_iter()
.chain(iter::once(forwarded_for_directive(remote_addr)))
.chain(header_host.map(|host| forwarded_host_directive(&host)))
.chain(iter::once(forwarded_proto_directive(forwarded_proto)))
.collect::<Vec<_>>()
.join(", "),
) {
headers.insert(FORWARDED, forwarded_value);
}
} else if let Ok(x_forwarded_value) = HeaderValue::from_str(
if let Ok(x_forwarded_value) = HeaderValue::from_str(
&x_forwarded_for
.iter()
.chain(iter::once(&remote_addr))
Expand All @@ -118,6 +112,11 @@ impl HeaderRewriter {
) {
headers.insert("x-forwarded-for", x_forwarded_value);
}

headers.insert(
"x-forwarded-proto",
HeaderValue::from_static(forwarded_proto),
);
}

pub fn post_process(&self, headers: &mut HeaderMap) {
Expand All @@ -138,11 +137,6 @@ impl Builder {
self
}

pub fn use_std_forwarded(mut self, use_std: bool) -> Self {
self.inner.use_std_forwarded = use_std;
self
}

pub fn set_via(mut self, via: HeaderValue) -> Self {
self.inner.set_via = Some(via);
self
Expand Down Expand Up @@ -207,6 +201,7 @@ mod test {
headers.get(FORWARDED).unwrap(),
"for=192.168.0.1, for=127.0.0.1, host=example.com, proto=http"
);
assert_eq!(headers.get("x-forwarded-for").unwrap(), "127.0.0.1");
assert_eq!(headers.get("x-forwarded-proto").unwrap(), "http");

let mut headers = HeaderMap::new();
Expand All @@ -232,7 +227,6 @@ mod test {

let rewriter = HeaderRewriter::builder()
.trust_upstream_headers(true)
.use_std_forwarded(true)
.build();
rewriter.pre_process(
&mut headers,
Expand All @@ -244,6 +238,7 @@ mod test {
headers.get(FORWARDED).unwrap(),
"for=192.168.0.1, for=\"[::1]\", host=example.com, proto=http"
);
assert_eq!(headers.get("x-forwarded-for").unwrap(), "192.168.0.1, ::1");
assert_eq!(headers.get("x-forwarded-proto").unwrap(), "http");
}

Expand Down
1 change: 0 additions & 1 deletion taxy/src/proxy/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ impl HttpPortContext {
router: Router::new(proxies),
header_rewriter: HeaderRewriter::builder()
.trust_upstream_headers(false)
.use_std_forwarded(true)
.set_via(HeaderValue::from_static("taxy"))
.build(),
}));
Expand Down
10 changes: 0 additions & 10 deletions taxy/tests/http_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ async fn http_proxy() -> anyhow::Result<()> {
let mock_get = server
.mock("GET", "/hello?world=1")
.match_header("via", "taxy")
.match_header("x-forwarded-for", mockito::Matcher::Missing)
.match_header("x-forwarded-host", mockito::Matcher::Missing)
.match_header("x-real-ip", mockito::Matcher::Missing)
.match_header("x-forwarded-proto", "http")
.match_header("accept-encoding", "gzip, br")
Expand All @@ -28,8 +26,6 @@ async fn http_proxy() -> anyhow::Result<()> {
let mock_get_with_path = server
.mock("GET", "/Hello?world=1")
.match_header("via", "taxy")
.match_header("x-forwarded-for", mockito::Matcher::Missing)
.match_header("x-forwarded-host", mockito::Matcher::Missing)
.match_header("x-real-ip", mockito::Matcher::Missing)
.match_header("x-forwarded-proto", "http")
.match_header("accept-encoding", "gzip, br")
Expand All @@ -40,8 +36,6 @@ async fn http_proxy() -> anyhow::Result<()> {
let mock_get_trailing_slash = server
.mock("GET", "/hello/?world=1")
.match_header("via", "taxy")
.match_header("x-forwarded-for", mockito::Matcher::Missing)
.match_header("x-forwarded-host", mockito::Matcher::Missing)
.match_header("x-real-ip", mockito::Matcher::Missing)
.match_header("x-forwarded-proto", "http")
.match_header("accept-encoding", "gzip, br")
Expand All @@ -52,8 +46,6 @@ async fn http_proxy() -> anyhow::Result<()> {
let mock_post = server
.mock("POST", "/hello?world=1")
.match_header("via", "taxy")
.match_header("x-forwarded-for", mockito::Matcher::Missing)
.match_header("x-forwarded-host", mockito::Matcher::Missing)
.match_header("x-real-ip", mockito::Matcher::Missing)
.match_header("x-forwarded-proto", "http")
.match_header("accept-encoding", "gzip, br")
Expand All @@ -67,8 +59,6 @@ async fn http_proxy() -> anyhow::Result<()> {
let mock_stream = server
.mock("POST", "/hello?world=1")
.match_header("via", "taxy")
.match_header("x-forwarded-for", mockito::Matcher::Missing)
.match_header("x-forwarded-host", mockito::Matcher::Missing)
.match_header("x-real-ip", mockito::Matcher::Missing)
.match_header("x-forwarded-proto", "http")
.match_header("accept-encoding", "gzip, br")
Expand Down

0 comments on commit 64711a4

Please sign in to comment.