diff --git a/manager-solution/manager/manager.py b/manager-solution/manager/manager.py index 89f6637..c32c729 100644 --- a/manager-solution/manager/manager.py +++ b/manager-solution/manager/manager.py @@ -13,6 +13,7 @@ import socket import threading import time from typing import Any, Dict, Iterable, Optional +from urllib.parse import urlsplit import docker @@ -274,7 +275,14 @@ def extract_user_from_http_request(data: bytes, known_users: Dict[str, Dict[str, if candidate in known_users and candidate not in {"localhost", "127", "0"}: return known_users[candidate], data, None - path, separator, query = target.partition("?") + parsed_target = urlsplit(target) + if parsed_target.scheme and parsed_target.netloc: + path = parsed_target.path or "/" + query = parsed_target.query + separator = "?" if query else "" + else: + path, separator, query = target.partition("?") + segments = [segment for segment in path.split("/") if segment] if segments: candidate = segments[0] @@ -530,7 +538,7 @@ async def main(): log( "Shared gateway ready: " f"{format_access_url('localhost', GATEWAY_PORT)} " - "(host-based routing: http://.localhost:{GATEWAY_PORT})" + f"(host-based routing: http://.localhost:{GATEWAY_PORT})" ) servers.append(gateway_server) diff --git a/manager-solution/manager/test_manager.py b/manager-solution/manager/test_manager.py index fabcf67..ec36b7b 100644 --- a/manager-solution/manager/test_manager.py +++ b/manager-solution/manager/test_manager.py @@ -221,6 +221,52 @@ class ManagerConfigTests(unittest.TestCase): ) self.assertIsNone(redirect_target) + def test_extract_user_from_bare_user_path_rewrites_to_root(self): + request = ( + b"GET /user1 HTTP/1.1\r\n" + b"Host: 10.200.200.113:8080\r\n" + b"Connection: keep-alive\r\n" + b"\r\n" + ) + users = {"user1": {"id": "user1"}} + + user, rewritten, redirect_target = self.manager.extract_user_from_http_request(request, users) + + self.assertEqual(user["id"], "user1") + self.assertEqual( + rewritten, + ( + b"GET / HTTP/1.1\r\n" + b"Host: 10.200.200.113:8080\r\n" + b"Connection: keep-alive\r\n" + b"\r\n" + ), + ) + self.assertIsNone(redirect_target) + + def test_extract_user_from_absolute_form_request_rewrites_to_root(self): + request = ( + b"GET http://10.200.200.113:8080/user1 HTTP/1.1\r\n" + b"Host: 10.200.200.113:8080\r\n" + b"Connection: keep-alive\r\n" + b"\r\n" + ) + users = {"user1": {"id": "user1"}} + + user, rewritten, redirect_target = self.manager.extract_user_from_http_request(request, users) + + self.assertEqual(user["id"], "user1") + self.assertEqual( + rewritten, + ( + b"GET / HTTP/1.1\r\n" + b"Host: 10.200.200.113:8080\r\n" + b"Connection: keep-alive\r\n" + b"\r\n" + ), + ) + self.assertIsNone(redirect_target) + def test_wait_until_ready_applies_stabilization_delay(self): sleep_calls = [] clock = {"now": 0.0}