@@ -9,6 +9,7 @@ use std::sync::Arc;
9
9
use anyhow:: Context ;
10
10
use axum:: async_trait;
11
11
use bytes:: { BufMut , Bytes , BytesMut } ;
12
+ use http:: uri:: Scheme ;
12
13
use hyper:: header;
13
14
use pingora:: http:: { RequestHeader , ResponseHeader } ;
14
15
use pingora:: protocols:: http:: error_resp;
@@ -310,9 +311,6 @@ impl ProxyHttp for Gateway {
310
311
311
312
upstream_request. set_uri ( new_uri) ;
312
313
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.
316
314
if let Some ( ref host) = gateway_ctx. upstream_host {
317
315
upstream_request. insert_header ( header:: HOST , host) ?;
318
316
}
@@ -324,6 +322,45 @@ impl ProxyHttp for Gateway {
324
322
) ?;
325
323
}
326
324
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
+
327
364
let svc_auth_method = self
328
365
. inner
329
366
. service_registry
0 commit comments