Fix for new version of websockets, remove http_parser dependency in tests, fix tests to allow running from a virtualenv

This commit is contained in:
Gabriel Sztejnworcel
2025-09-18 19:22:17 +00:00
parent 00685aee3a
commit fbf5ec15dd
5 changed files with 47 additions and 16 deletions
+2
View File
@@ -21,6 +21,8 @@ As you can see from the items above, using this tool could change the behavior o
### Dependencies
The tool was tested with Python versions 3.10.2 and 3.10.4. To install the dependencies:
```
python -m venv .venv
.venv\Scripts\activate.bat
pip install -r requirements.txt
```
### Usage
+2 -2
View File
@@ -97,8 +97,8 @@ def pipe_client_to_ws_server(ws_server_conn, pipe, loop):
pipe_helper.close_handle_ignore_error(pipe)
async def ws_server_handler(ws_server_conn, path):
if path == f'/pipe/{config_handler.Config.pipe_name}':
async def ws_server_handler(ws_server_conn):
if ws_server_conn.request.path == f'/pipe/{config_handler.Config.pipe_name}':
pipe = pipe_helper.create_pipe_client(config_handler.Config.pipe_fullpath)
ws_to_pipe_task = asyncio.create_task(ws_server_to_pipe_client(ws_server_conn, pipe))
+1 -2
View File
@@ -1,7 +1,6 @@
websockets
websockets>=10
websocket-client
pywin32
asyncio
pytest
uuid
http_parser
+39 -10
View File
@@ -1,6 +1,6 @@
import asyncio
import logging
from http_parser.pyparser import HttpParser
# from http_parser.pyparser import HttpParser
HTTP_PROXY_PORT = 9999
@@ -30,24 +30,53 @@ async def proxy_server_handler(server_reader, server_writer):
def handle_connect_request(req: bytes):
parser = HttpParser()
parsed_len = parser.execute(req, len(req))
# Find end of headers
hdr_end = req.find(b"\r\n\r\n")
if hdr_end == -1:
raise ProxyException(f'Invalid request (no header terminator): {req!r}')
if parsed_len != len(req):
raise ProxyException(f'Invalid request: {req}')
# Decode headers using ISO-8859-1 per HTTP spec
try:
head = req[:hdr_end].decode("iso-8859-1")
except UnicodeDecodeError:
raise ProxyException('Invalid request encoding (expected ISO-8859-1)')
lines = head.split("\r\n")
if not lines or not lines[0]:
raise ProxyException(f'Invalid request line: {lines[:1]!r}')
# Parse request line: METHOD SP REQUEST-TARGET SP HTTP/VERSION
parts = lines[0].split()
if len(parts) != 3:
raise ProxyException(f'Invalid request line: {lines[0]!r}')
method, _target, version = parts
method = parser.get_method()
if method != 'CONNECT':
raise ProxyException(f'Invalid request method: {method}')
if not version.startswith("HTTP/"):
raise ProxyException(f'Invalid HTTP version: {version!r}')
host = parser.get_headers()['HOST']
host_split = host.split(':')
# Parse headers (very small, case-insensitive)
headers = {}
for raw in lines[1:]:
if not raw:
continue
if ":" not in raw:
raise ProxyException(f'Malformed header: {raw!r}')
k, v = raw.split(":", 1)
headers[k.strip().lower()] = v.lstrip()
# Match original behavior: read the authority from the Host header
if "host" not in headers:
raise ProxyException('Missing Host header')
host_hdr = headers["host"]
host_split = host_hdr.split(':')
if len(host_split) != 2:
raise ProxyException(f'Invalid host: {host}')
raise ProxyException(f'Invalid host: {host_hdr}')
host = host_split[0]
port = host_split[1]
port = host_split[1] # keep as string to preserve original function signature
return host, port
+3 -2
View File
@@ -3,6 +3,7 @@ import uuid
import win32file
import subprocess
import time
import sys
HTTP_PROXY_PORT = 9999
@@ -21,11 +22,11 @@ def server_to_client_flow(sent_msg: bytes, expected_rcvd_msg: bytes):
pipe_name = str(uuid.uuid4())
pipe_intercept_process = subprocess.Popen(
['python', 'pipe_intercept.py', '--pipe-name', pipe_name, '--http-proxy-port', f'{HTTP_PROXY_PORT}', '--log-level', 'DEBUG'],
[sys.executable, 'pipe_intercept.py', '--pipe-name', pipe_name, '--http-proxy-port', f'{HTTP_PROXY_PORT}', '--log-level', 'DEBUG'],
creationflags=subprocess.CREATE_NEW_CONSOLE)
time.sleep(1)
ws_proxy_process = subprocess.Popen(['python', 'tests/http_proxy.py'], creationflags=subprocess.CREATE_NEW_CONSOLE)
ws_proxy_process = subprocess.Popen([sys.executable, 'tests/http_proxy.py'], creationflags=subprocess.CREATE_NEW_CONSOLE)
time.sleep(2)
pipe_server, pipe_client = create_pipe_client_server(pipe_name)