diff --git a/manager-solution/manager/manager.py b/manager-solution/manager/manager.py index 0d44b87..89f6637 100644 --- a/manager-solution/manager/manager.py +++ b/manager-solution/manager/manager.py @@ -230,27 +230,19 @@ def build_http_redirect(location: str) -> bytes: return "\r\n".join(headers).encode("utf-8") -def build_user_host(host: str, user_id: str) -> Optional[str]: - if not host: - return None +def rewrite_http_request_target(data: bytes, target: str) -> bytes: + header_end = data.find(b"\r\n") + if header_end == -1: + return data - hostname, separator, port = host.partition(":") - hostname = hostname.strip().lower() - if not hostname: - return None + request_line = data[:header_end].decode("iso-8859-1", errors="replace") + parts = request_line.split(" ", 2) + if len(parts) != 3: + return data - if hostname == "localhost": - target_host = f"{user_id}.localhost" - else: - labels = [label for label in hostname.split(".") if label] - if not labels: - return None - if labels[0] == user_id: - target_host = hostname - else: - target_host = ".".join([user_id, *labels]) - - return f"{target_host}:{port}" if separator else target_host + method, _, version = parts + rewritten_line = f"{method} {target} {version}".encode("iso-8859-1") + return rewritten_line + data[header_end:] def extract_user_from_http_request(data: bytes, known_users: Dict[str, Dict[str, Any]]): @@ -287,13 +279,10 @@ def extract_user_from_http_request(data: bytes, known_users: Dict[str, Dict[str, if segments: candidate = segments[0] if candidate in known_users: - user_host = build_user_host(headers.get("host", ""), candidate) - if user_host: - redirect_path = "/" + "/".join(segments[1:]) if len(segments) > 1 else "/" - if separator: - redirect_path = f"{redirect_path}?{query}" - redirect_target = f"http://{user_host}{redirect_path}" - return None, data, redirect_target + rewritten_path = "/" + "/".join(segments[1:]) if len(segments) > 1 else "/" + rewritten_target = f"{rewritten_path}?{query}" if separator else rewritten_path + rewritten_data = rewrite_http_request_target(data, rewritten_target) + return known_users[candidate], rewritten_data, None return None, data, None diff --git a/manager-solution/manager/test_manager.py b/manager-solution/manager/test_manager.py index 71f3353..fabcf67 100644 --- a/manager-solution/manager/test_manager.py +++ b/manager-solution/manager/test_manager.py @@ -198,7 +198,7 @@ class ManagerConfigTests(unittest.TestCase): self.assertEqual(rewritten, request) self.assertIsNone(redirect_target) - def test_extract_user_from_path_returns_redirect_target(self): + def test_extract_user_from_path_rewrites_request_for_direct_proxying(self): request = ( b"GET /user1/websockify?token=abc HTTP/1.1\r\n" b"Host: localhost:8080\r\n" @@ -209,9 +209,17 @@ class ManagerConfigTests(unittest.TestCase): user, rewritten, redirect_target = self.manager.extract_user_from_http_request(request, users) - self.assertIsNone(user) - self.assertEqual(rewritten, request) - self.assertEqual(redirect_target, "http://user1.localhost:8080/websockify?token=abc") + self.assertEqual(user["id"], "user1") + self.assertEqual( + rewritten, + ( + b"GET /websockify?token=abc HTTP/1.1\r\n" + b"Host: localhost:8080\r\n" + b"Upgrade: websocket\r\n" + b"\r\n" + ), + ) + self.assertIsNone(redirect_target) def test_wait_until_ready_applies_stabilization_delay(self): sleep_calls = []