Skip to content

Commit 6a29f78

Browse files
committed
feat: add optional proxy header stripping in inbound request processing
1 parent 0519d0b commit 6a29f78

1 file changed

Lines changed: 38 additions & 2 deletions

File tree

backend/app/main.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,38 @@ async def inbound(request: Request):
9898
headers_ordered: List[Tuple[str, str]] = [
9999
(k.decode("latin-1"), v.decode("latin-1")) for (k, v) in headers_scope
100100
]
101+
102+
# Optional proxy stripping: if PROXY_HOSTNAME matches x-forwarded-host, strip that proxy's headers
103+
proxy_host = os.getenv("PROXY_HOSTNAME")
104+
xf_host = request.headers.get("x-forwarded-host")
105+
if proxy_host and xf_host:
106+
proxy_host_l = proxy_host.strip().lower()
107+
xf_hosts = [h.strip().lower() for h in xf_host.split(",") if h.strip()]
108+
if proxy_host_l in xf_hosts:
109+
remove_all = {
110+
# handled specially below for partial removal
111+
# 'x-forwarded-host',
112+
"x-forwarded-port",
113+
"x-forwarded-proto",
114+
"x-forwarded-server",
115+
"x-real-ip",
116+
}
117+
filtered: List[Tuple[str, str]] = []
118+
for k, v in headers_ordered:
119+
kl = k.lower()
120+
if kl in remove_all:
121+
# drop these headers entirely when the target proxy is present
122+
continue
123+
if kl == "x-forwarded-host":
124+
# Remove only the matching proxy hostname from the comma-separated list
125+
parts = [p.strip() for p in v.split(",") if p.strip()]
126+
kept = [p for p in parts if p.lower() != proxy_host_l]
127+
if kept:
128+
filtered.append((k, ", ".join(kept)))
129+
# if none left, drop the header entirely
130+
continue
131+
filtered.append((k, v))
132+
headers_ordered = filtered
101133
# Reconstruct a raw-like HTTP request stream (approximate; header casing may differ)
102134
http_version = request.scope.get("http_version", "1.1")
103135
target = request.url.path
@@ -109,13 +141,17 @@ async def inbound(request: Request):
109141
for name, value in headers_ordered
110142
)
111143
raw_bytes = start_line + header_lines + b"\r\n" + (body or b"")
144+
# Build headers dict from filtered ordered list to keep removals consistent
145+
headers_dict: Dict[str, str] = {}
146+
for k, v in headers_ordered:
147+
headers_dict[k] = v
112148
item = StoredRequest(
113149
id=_next_id,
114150
method=request.method,
115151
path=request.url.path,
116-
ts=datetime.now(timezone.utc).timestamp(),
152+
ts=datetime.now(timezone.utc).timestamp(),
117153
ip=request.client.host if request.client else "",
118-
headers={k: v for k, v in request.headers.items()},
154+
headers=headers_dict,
119155
headers_ordered=headers_ordered,
120156
query={k: v for k, v in request.query_params.items()},
121157
body_text=body_text,

0 commit comments

Comments
 (0)