Skip to content

Commit 5536812

Browse files
committed
Ensures MATLAB proxy manager correctly forwards client request headers.
1 parent 96d17ec commit 5536812

File tree

2 files changed

+77
-17
lines changed

2 files changed

+77
-17
lines changed

matlab_proxy_manager/web/app.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ async def proxy(req):
232232

233233
# Set content length in case of modification
234234
req_headers["Content-Length"] = str(len(req_body))
235-
req_headers["x-forwarded-proto"] = "http"
235+
req_headers["X-Forwarded-Proto"] = "http"
236236
req_path = req.rel_url
237237

238238
# Redirect block to move /*/matlab to /*/matlab/default/
@@ -272,9 +272,11 @@ async def proxy(req):
272272
and req_headers.get(upgrade, "").lower() == "websocket"
273273
and req.method == "GET"
274274
):
275-
return await _handle_websocket_request(req, proxy_url)
275+
return await _forward_websocket_request(req, proxy_url)
276276
try:
277-
return await _handle_http_request(req, req_body, proxy_url, backend_server)
277+
return await _forward_http_request(
278+
req, req_body, proxy_url, _collate_headers(req_headers, backend_server)
279+
)
278280
except web.HTTPFound:
279281
log.debug("Redirection to path with /default")
280282
raise
@@ -295,7 +297,20 @@ async def proxy(req):
295297
# Helper private functions
296298

297299

298-
async def _handle_websocket_request(
300+
def _collate_headers(req_headers: dict, backend_server: dict) -> dict:
301+
"""Combines request headers with backend server (matlab-proxy) headers.
302+
303+
Args:
304+
req_headers (dict): The headers from the incoming request.
305+
backend_server (dict): The backend server configuration.
306+
307+
Returns:
308+
dict: A new dictionary containing all headers from both sources.
309+
"""
310+
return {**req_headers, **backend_server.get("headers")}
311+
312+
313+
async def _forward_websocket_request(
299314
req: web.Request, proxy_url: str
300315
) -> web.WebSocketResponse:
301316
"""Handles a websocket request to the backend matlab proxy server
@@ -381,8 +396,11 @@ async def ws_forward(ws_src, ws_dest):
381396
raise aiohttp.WebSocketError(code=code, message=message)
382397

383398

384-
async def _handle_http_request(
385-
req: web.Request, req_body: Optional[bytes], proxy_url: str, backend_server: dict
399+
async def _forward_http_request(
400+
req: web.Request,
401+
req_body: Optional[bytes],
402+
proxy_url: str,
403+
headers: dict,
386404
) -> web.Response:
387405
"""
388406
Forwards an incoming HTTP request to a specified backend server.
@@ -396,7 +414,7 @@ async def _handle_http_request(
396414
proxy_url,
397415
allow_redirects=True,
398416
data=req_body,
399-
headers=backend_server.get("headers"),
417+
headers=headers,
400418
) as res:
401419
headers = res.headers.copy()
402420
body = await res.read()

tests/unit/proxy-manager/web/test_app.py

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -259,14 +259,14 @@ async def test_proxy_websocket_request(self, mocker):
259259
"matlab_proxy_manager.web.app._get_backend_server",
260260
return_value={"absolute_url": "http://server1"},
261261
)
262-
mock_handle_websocket = mocker.patch(
263-
"matlab_proxy_manager.web.app._handle_websocket_request",
262+
mock_forward_websocket = mocker.patch(
263+
"matlab_proxy_manager.web.app._forward_websocket_request",
264264
return_value=web.WebSocketResponse(),
265265
)
266266

267267
await app.proxy(mock_req)
268268

269-
mock_handle_websocket.assert_called_once()
269+
mock_forward_websocket.assert_called_once()
270270

271271
async def test_proxy_http_request(self, mocker):
272272
"""
@@ -284,16 +284,16 @@ async def test_proxy_http_request(self, mocker):
284284

285285
mocker.patch(
286286
"matlab_proxy_manager.web.app._get_backend_server",
287-
return_value={"absolute_url": "http://server"},
287+
return_value={"absolute_url": "http://server", "headers": {}},
288288
)
289-
mock_handle_http = mocker.patch(
290-
"matlab_proxy_manager.web.app._handle_http_request",
289+
mock_forward_http = mocker.patch(
290+
"matlab_proxy_manager.web.app._forward_http_request",
291291
return_value=web.Response(),
292292
)
293293

294294
await app.proxy(mock_req)
295295

296-
mock_handle_http.assert_called_once()
296+
mock_forward_http.assert_called_once()
297297

298298
async def test_proxy_server_disconnected(self, mocker):
299299
"""
@@ -310,10 +310,10 @@ async def test_proxy_server_disconnected(self, mocker):
310310

311311
mocker.patch(
312312
"matlab_proxy_manager.web.app._get_backend_server",
313-
return_value={"absolute_url": "http://backend"},
313+
return_value={"absolute_url": "http://backend", "headers": {}},
314314
)
315315
mocker.patch(
316-
"matlab_proxy_manager.web.app._handle_http_request",
316+
"matlab_proxy_manager.web.app._forward_http_request",
317317
side_effect=client_exceptions.ServerDisconnectedError,
318318
)
319319

@@ -339,13 +339,55 @@ async def test_proxy_unexpected_exception(self, mocker):
339339
return_value={"absolute_url": "http://backend"},
340340
)
341341
mocker.patch(
342-
"matlab_proxy_manager.web.app._handle_http_request",
342+
"matlab_proxy_manager.web.app._forward_http_request",
343343
side_effect=Exception("Unexpected error"),
344344
)
345345

346346
with pytest.raises(web.HTTPNotFound):
347347
await app.proxy(mock_req)
348348

349+
async def test_proxy_correct_req_headers_are_forwarded(self, mocker):
350+
"""
351+
Test that the correct request headers are forwarded to the backend server.
352+
353+
This test ensures that the proxy function correctly forwards the necessary
354+
headers to the backend server, including the MWI-MPM-CONTEXT header.
355+
"""
356+
mock_req = mocker.AsyncMock()
357+
mock_req.read = mocker.AsyncMock(return_value=b"request_body")
358+
mock_req.rel_url = "/matlab/default/some/path"
359+
mock_req.headers = {
360+
"JSESSION-ID": "123456789",
361+
"MWI-MPM-CONTEXT": "test_context",
362+
}
363+
mock_req.method = "GET"
364+
365+
mocker.patch(
366+
"matlab_proxy_manager.web.app._get_backend_server",
367+
return_value={
368+
"absolute_url": "http://server1",
369+
"headers": {"MWI-AUTH-TOKEN": "token"},
370+
},
371+
)
372+
mock_forward_http = mocker.patch(
373+
"matlab_proxy_manager.web.app._forward_http_request",
374+
return_value=web.Response(),
375+
)
376+
await app.proxy(mock_req)
377+
mock_forward_http.assert_called_once_with(
378+
mock_req,
379+
b"request_body",
380+
"http://server1/some/path",
381+
{
382+
**mock_req.headers,
383+
**{
384+
"MWI-AUTH-TOKEN": "token",
385+
"Content-Length": "12",
386+
"X-Forwarded-Proto": "http",
387+
},
388+
},
389+
)
390+
349391

350392
@pytest.fixture
351393
def patch_env_vars(monkeypatch):

0 commit comments

Comments
 (0)