@@ -123,6 +123,16 @@ def get_workspace_repository(
123123 ]
124124)
125125
126+ # Do not forward spoofed reverse-proxy informational headers:
127+ STRIP_REQUEST_HEADERS = HOP_BY_HOP_HEADERS | {
128+ "host" ,
129+ "x-forwarded-for" ,
130+ "x-forwarded-host" ,
131+ "x-forwarded-proto" ,
132+ "x-real-ip" ,
133+ "forwarded" ,
134+ }
135+
126136# Define paths that do not require X-Workspace header
127137AUTH_WHITELIST_PATTERNS = [
128138 re .compile (p )
@@ -134,11 +144,24 @@ def get_workspace_repository(
134144
135145
136146@app .get ("/api/capabilities.json" )
137- async def capabilities ():
147+ async def capabilities (request : Request ):
138148 """Proxy OSM capabilities manifest without requiring authentication."""
139149
150+ client_host = request .client .host if request .client else "unknown"
151+ req_headers = [
152+ (k .encode (), v .encode ())
153+ for k , v in request .headers .items ()
154+ if k .lower () not in STRIP_REQUEST_HEADERS
155+ ] + [
156+ (b"Host" , _osm_client .base_url .host .encode ()),
157+ (b"X-Real-IP" , client_host .encode ()),
158+ (b"X-Forwarded-For" , client_host .encode ()),
159+ (b"X-Forwarded-Host" , (request .url .hostname or "" ).encode ()),
160+ (b"X-Forwarded-Proto" , request .url .scheme .encode ()),
161+ ]
162+
140163 url = httpx .URL (path = "/api/capabilities.json" )
141- rp_req = _osm_client .build_request ("GET" , url )
164+ rp_req = _osm_client .build_request ("GET" , url , headers = req_headers )
142165
143166 try :
144167 rp_resp = await _osm_client .send (rp_req , stream = True )
@@ -207,16 +230,21 @@ async def catch_all(
207230 )
208231
209232 client = _osm_client
210-
211- # Forward all request headers except the hop-by-hops:
212- new_headers = [
233+ client_host = request .client .host if request .client else "unknown"
234+ req_headers = [
213235 (k .encode (), v .encode ())
214236 for k , v in request .headers .items ()
215- if k .lower () not in HOP_BY_HOP_HEADERS
237+ if k .lower () not in STRIP_REQUEST_HEADERS
238+ ] + [
239+ (b"Host" , client .base_url .host .encode ()),
240+ (b"X-Real-IP" , client_host .encode ()),
241+ (b"X-Forwarded-For" , client_host .encode ()),
242+ (b"X-Forwarded-Host" , (request .url .hostname or "" ).encode ()),
243+ (b"X-Forwarded-Proto" , request .url .scheme .encode ()),
216244 ]
217245
218246 rp_req = client .build_request (
219- request .method , url , headers = new_headers , content = request .stream ()
247+ request .method , url , headers = req_headers , content = request .stream ()
220248 )
221249 try :
222250 rp_resp = await client .send (rp_req , stream = True )
0 commit comments