Skip to content

fix(client-api): parse single-IP X-Forwarded-For values#4839

Merged
bfops merged 2 commits into
clockworklabs:masterfrom
Ludv1gL:fix/xforwardedfor-single-ip
Jun 29, 2026
Merged

fix(client-api): parse single-IP X-Forwarded-For values#4839
bfops merged 2 commits into
clockworklabs:masterfrom
Ludv1gL:fix/xforwardedfor-single-ip

Conversation

@Ludv1gL

@Ludv1gL Ludv1gL commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Summary

XForwardedFor::decode requires a comma and fails to decode X-Forwarded-For: 1.2.3.4.
Under axum 0.8 this now surfaces as HTTP 400 on every single-hop-proxy request.

Fix

Accept comma-separated or single-IP values — take the first entry either way.

Reproducer

Any browser going through a proxy that does .insert("x-forwarded-for", client_ip)
(standard single-hop pattern) sees 400 Bad Request on WebSocket subscribe.

Version regression

Bug latent since the axum migration in 2023-06 (commit b4dae74). axum 0.7
silently dropped the decoder error via Option<TypedHeader<T>>; axum 0.8
(#2713) promotes it to a 400 rejection.

`XForwardedFor::decode` required a comma in the header value via
`split_once(',').ok_or_else(headers::Error::invalid)?`, so any client
coming through a single-hop proxy — which emits `X-Forwarded-For: <ip>`
with no comma — failed to decode.

Previously this was silent: `Option<TypedHeader<XForwardedFor>>` in
`crates/client-api/src/routes/subscribe.rs` resolved to `None` on
decode error under axum 0.7. axum 0.8 (landed in clockworklabs#2713) changed the
behavior: the same decoder `Err` now surfaces as a 400 Bad Request,
which breaks all WebSocket subscribe requests from single-hop proxy
clients — reproducible with:

```
curl -v -H 'Connection: Upgrade' -H 'Upgrade: websocket' \
  -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==' \
  -H 'Sec-WebSocket-Protocol: v2.bsatn.spacetimedb' \
  -H 'x-forwarded-for: 1.2.3.4' \
  "http://127.0.0.1:3000/v1/database/test/subscribe?token=..."
# => HTTP/1.1 400 Bad Request
# => invalid HTTP header (x-forwarded-for)
```

Accept both comma-separated and single-IP forms: take the first
entry (trimmed) regardless of whether a comma is present. This
matches how Nginx, Apache, HAProxy, etc. read the same header.
@bfops bfops enabled auto-merge June 29, 2026 16:07
@bfops bfops disabled auto-merge June 29, 2026 16:12
@bfops bfops enabled auto-merge June 29, 2026 18:20
@bfops bfops added this pull request to the merge queue Jun 29, 2026
Merged via the queue into clockworklabs:master with commit c9c7115 Jun 29, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants