andito HF Staff commited on
Commit
a2d5469
·
verified ·
1 Parent(s): 6147c55

Forward client IP chain to session allocator

Browse files

Preserve the incoming X-Forwarded-For chain for load-balancer network attribution. Requests without the header continue to omit it.

Files changed (3) hide show
  1. README.md +2 -1
  2. app.py +1 -0
  3. tests/test_session_proxy.py +11 -0
README.md CHANGED
@@ -31,4 +31,5 @@ Optional:
31
  - `GET /session-url`: returns the currently configured upstream allocator URL
32
  - `GET /config`: alias for `/session-url`
33
  - `POST /session`: proxies the session allocation request to the upstream URL,
34
- including a valid incoming bearer `Authorization` header when present
 
 
31
  - `GET /session-url`: returns the currently configured upstream allocator URL
32
  - `GET /config`: alias for `/session-url`
33
  - `POST /session`: proxies the session allocation request to the upstream URL,
34
+ including valid incoming bearer `Authorization` and `X-Forwarded-For`
35
+ headers when present
app.py CHANGED
@@ -74,6 +74,7 @@ def _upstream_headers(request: Request) -> dict[str, str]:
74
  "Content-Type": request.headers.get("content-type"),
75
  "Accept": request.headers.get("accept"),
76
  "Authorization": _bearer_authorization(request.headers.get("authorization")),
 
77
  }
78
  headers.update({name: value for name, value in forwarded_headers.items() if value})
79
  return headers
 
74
  "Content-Type": request.headers.get("content-type"),
75
  "Accept": request.headers.get("accept"),
76
  "Authorization": _bearer_authorization(request.headers.get("authorization")),
77
+ "X-Forwarded-For": request.headers.get("x-forwarded-for"),
78
  }
79
  headers.update({name: value for name, value in forwarded_headers.items() if value})
80
  return headers
tests/test_session_proxy.py CHANGED
@@ -98,8 +98,19 @@ class SessionProxyTests(unittest.IsolatedAsyncioTestCase):
98
  post = await self.proxy({})
99
 
100
  self.assertNotIn("Authorization", post["headers"])
 
101
 
102
  async def test_does_not_forward_non_bearer_authorization(self):
103
  post = await self.proxy({"Authorization": "Basic credentials"})
104
 
105
  self.assertNotIn("Authorization", post["headers"])
 
 
 
 
 
 
 
 
 
 
 
98
  post = await self.proxy({})
99
 
100
  self.assertNotIn("Authorization", post["headers"])
101
+ self.assertNotIn("X-Forwarded-For", post["headers"])
102
 
103
  async def test_does_not_forward_non_bearer_authorization(self):
104
  post = await self.proxy({"Authorization": "Basic credentials"})
105
 
106
  self.assertNotIn("Authorization", post["headers"])
107
+
108
+ async def test_forwards_client_ip_chain_to_upstream(self):
109
+ post = await self.proxy(
110
+ {"X-Forwarded-For": "203.0.113.8, 10.0.0.4"}
111
+ )
112
+
113
+ self.assertEqual(
114
+ post["headers"]["X-Forwarded-For"],
115
+ "203.0.113.8, 10.0.0.4",
116
+ )