Skip to content

Commit a0fd97f

Browse files
authored
core/gateway: set x-forwarded headers (#1927)
related to #1926
1 parent 55977e8 commit a0fd97f

File tree

1 file changed

+40
-3
lines changed
  • runtimes/core/src/api/gateway

1 file changed

+40
-3
lines changed

runtimes/core/src/api/gateway/mod.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::sync::Arc;
99
use anyhow::Context;
1010
use axum::async_trait;
1111
use bytes::{BufMut, Bytes, BytesMut};
12+
use http::uri::Scheme;
1213
use hyper::header;
1314
use pingora::http::{RequestHeader, ResponseHeader};
1415
use pingora::protocols::http::error_resp;
@@ -310,9 +311,6 @@ impl ProxyHttp for Gateway {
310311

311312
upstream_request.set_uri(new_uri);
312313

313-
// Do we need to set the host header here?
314-
// It means the upstream service won't be able to tell
315-
// what the original Host header was, which is sometimes useful.
316314
if let Some(ref host) = gateway_ctx.upstream_host {
317315
upstream_request.insert_header(header::HOST, host)?;
318316
}
@@ -324,6 +322,45 @@ impl ProxyHttp for Gateway {
324322
)?;
325323
}
326324

325+
// Set X-Forwarded-* headers, based on https://cs.opensource.google/go/go/+/refs/tags/go1.24.3:src/net/http/httputil/reverseproxy.go;l=78
326+
if let Some(client_addr) = session.client_addr().and_then(|addr| addr.as_inet()) {
327+
let client_ip = client_addr.ip().to_string();
328+
329+
let prior_headers = upstream_request
330+
.headers
331+
.get_all("x-forwarded-for")
332+
.iter()
333+
.filter_map(|v| std::str::from_utf8(v.as_bytes()).ok())
334+
.fold(String::new(), |mut acc, header| {
335+
if !acc.is_empty() {
336+
acc.push_str(", ");
337+
}
338+
acc.push_str(header);
339+
acc
340+
});
341+
342+
if !prior_headers.is_empty() {
343+
let combined = format!("{}, {}", prior_headers, client_ip);
344+
upstream_request.insert_header("x-forwarded-for", combined)?;
345+
} else {
346+
upstream_request.insert_header("x-forwarded-for", client_ip)?;
347+
}
348+
} else {
349+
upstream_request.remove_header("x-forwarded-for");
350+
}
351+
352+
if let Some(host) = session.req_header().headers.get(header::HOST) {
353+
upstream_request.insert_header("x-forwarded-host", host)?;
354+
}
355+
356+
upstream_request.insert_header(
357+
"x-forwarded-proto",
358+
match session.req_header().uri.scheme() == Some(&Scheme::HTTPS) {
359+
true => "https",
360+
false => "http",
361+
},
362+
)?;
363+
327364
let svc_auth_method = self
328365
.inner
329366
.service_registry

0 commit comments

Comments
 (0)