fix(wpt): serve XHR request header inspection fixture

Implement xhr/resources/inspect-headers.py with raw header names, duplicate
values, byte-preserving filters, and its upstream CORS response headers.
Support HEAD, uploads, and custom methods through the shared XHR dispatch,
and recognize the supported fixture references during case selection.

Validation: all 516 benchmark unit tests pass. 84 HTTP comparisons match
the unmodified upstream handler. With the same Moli binary, 31 WPT cases
improve from 9 to 18 passes and from 80 to 114 passing subtests, without
regressions.
This commit is contained in:
ldm0
2026-09-13 17:05:18 +08:00
parent ad9a298e27
commit cf2c749b30
3 changed files with 216 additions and 15 deletions
@@ -715,9 +715,9 @@ def _html_path_is_supported(
@lru_cache(maxsize=None)
def _xhr_url_handler_reference_patterns(directory: str) -> tuple[re.Pattern[str], ...]:
def _xhr_handler_reference_patterns(directory: str) -> tuple[re.Pattern[str], ...]:
references = []
for name in ("requri.py", "redirect.py"):
for name in ("requri.py", "redirect.py", "inspect-headers.py"):
resource = f"xhr/resources/{name}"
relative = posixpath.relpath(resource, directory)
references.extend(("/" + resource, relative, "./" + relative))
@@ -740,7 +740,7 @@ def _supported_wptserve_handler_references(
supported += SUPPORTED_WASM_WEBAPI_WPTSERVE_HANDLER_PATTERNS
if rel is not None and rel.startswith("xhr/"):
supported += SUPPORTED_XHR_DELAY_WPTSERVE_HANDLER_PATTERNS
supported += _xhr_url_handler_reference_patterns(rel.rsplit("/", 1)[0])
supported += _xhr_handler_reference_patterns(rel.rsplit("/", 1)[0])
if rel is not None and rel.startswith(
"html/semantics/scripting-1/the-script-element/module/"
):
@@ -69,9 +69,10 @@ from .case_set import (
DEFAULT_TESTHARNESS_TIMEOUT_SECONDS = 10.0
MAX_REQUEST_BODY_BYTES = 16 * 1024 * 1024
MAX_REQUEST_BODY_LINE_BYTES = 64 * 1024
XHR_URL_RESOURCE_PATHS = {
XHR_RESOURCE_PATHS = {
"/xhr/resources/requri.py",
"/xhr/resources/redirect.py",
"/xhr/resources/inspect-headers.py",
}
FETCH_ABORT_RESOURCE_PATHS = {
"/fetch/api/resources/stash-put.py",
@@ -1203,6 +1204,38 @@ def _xhr_redirect_fixture_response(
return code, "WEBSRT MARKETING", [("Location", location)], b"TEST", delay
def _xhr_inspect_headers_fixture_response(
query: str, raw_headers: list[tuple[str, str]]
) -> tuple[list[tuple[str, str]], bytes]:
"""Model xhr/resources/inspect-headers.py's raw header filtering."""
params = parse_qs(query, keep_blank_values=True, encoding="latin-1")
filter_value = params.get("filter_value", [""])[0].encode("latin-1")
filter_name = params.get("filter_name", [""])[0].encode("latin-1").lower()
parts = []
for raw_name, raw_value in raw_headers:
name, value = raw_name.encode("latin-1"), raw_value.encode("latin-1")
if filter_value:
if value == filter_value:
parts.append(name + b",")
elif name.lower() == filter_name:
parts.append(name + b": " + value + b"\n")
headers = []
if "cors" in params:
headers.extend([
("Access-Control-Allow-Origin", "*"),
("Access-Control-Allow-Credentials", "true"),
("Access-Control-Allow-Methods", "GET, POST, PUT, FOO"),
("Access-Control-Allow-Headers", "x-test, x-foo"),
(
"Access-Control-Expose-Headers",
"x-request-method, x-request-content-type, x-request-query, "
"x-request-content-length",
),
])
headers.append(("content-type", "text/plain"))
return headers, b"".join(parts)
def _redirect_fixture_response(query: str) -> tuple[int, str] | None:
"""Return the shared redirect response used by static WPT fixture handlers."""
@@ -1845,13 +1878,13 @@ def _make_handler(
if (
name.startswith("do_")
and unquote(urlsplit(getattr(self, "path", "")).path)
in XHR_URL_RESOURCE_PATHS
in XHR_RESOURCE_PATHS
):
return self._serve_xhr_url_method
return self._serve_xhr_method
raise AttributeError(name)
def _serve_xhr_url_method(self) -> None:
self._serve_xhr_url_resource(emit_body=self.command != "HEAD")
def _serve_xhr_method(self) -> None:
self._serve_xhr_resource(emit_body=self.command != "HEAD")
def do_GET(self) -> None: # noqa: N802 (BaseHTTPRequestHandler API)
if self.headers.get("Upgrade", "").lower() == "websocket":
@@ -1863,7 +1896,7 @@ def _make_handler(
self._serve(emit_body=False)
def do_OPTIONS(self) -> None: # noqa: N802
if self._serve_xhr_url_resource(emit_body=True):
if self._serve_xhr_resource(emit_body=True):
return
parsed = urlparse(self.path)
path = unquote(parsed.path)
@@ -1890,7 +1923,7 @@ def _make_handler(
self.send_error(404)
def do_POST(self) -> None: # noqa: N802
if self._serve_xhr_url_resource(emit_body=True):
if self._serve_xhr_resource(emit_body=True):
return
parsed = urlparse(self.path)
path = unquote(parsed.path)
@@ -1958,7 +1991,7 @@ def _make_handler(
self.end_headers()
def _serve_fetch_resource_method(self) -> None:
if self._serve_xhr_url_resource(emit_body=True):
if self._serve_xhr_resource(emit_body=True):
return
parsed = urlparse(self.path)
if unquote(parsed.path) in FETCH_ABORT_RESOURCE_PATHS:
@@ -1980,7 +2013,7 @@ def _make_handler(
do_DELETE = _serve_fetch_resource_method
def do_YO(self) -> None: # noqa: N802 (WPT custom method)
if self._serve_xhr_url_resource(emit_body=True):
if self._serve_xhr_resource(emit_body=True):
return
parsed = urlparse(self.path)
if unquote(parsed.path) in FETCH_ABORT_RESOURCE_PATHS | {
@@ -2108,7 +2141,7 @@ def _make_handler(
return
def _serve(self, *, emit_body: bool) -> None:
if self._serve_xhr_url_resource(emit_body=emit_body):
if self._serve_xhr_resource(emit_body=emit_body):
return
parsed = urlparse(self.path)
path = unquote(parsed.path)
@@ -2650,10 +2683,10 @@ def _make_handler(
self.send_error(status_code)
return False
def _serve_xhr_url_resource(self, *, emit_body: bool) -> bool:
def _serve_xhr_resource(self, *, emit_body: bool) -> bool:
parsed = urlsplit(self.path)
path = unquote(parsed.path)
if path not in XHR_URL_RESOURCE_PATHS:
if path not in XHR_RESOURCE_PATHS:
return False
try:
if path == "/xhr/resources/requri.py":
@@ -2669,6 +2702,11 @@ def _make_handler(
authority += ":" + str(self.server.server_address[1])
uri = f"http://{authority}{uri}"
status, reason, headers, body = 200, None, [], uri.encode("utf-8")
elif path == "/xhr/resources/inspect-headers.py":
status, reason = 200, None
headers, body = _xhr_inspect_headers_fixture_response(
parsed.query, list(self.headers.raw_items())
)
else:
status, reason, headers, body, delay = _xhr_redirect_fixture_response(
parsed.path, parsed.query
@@ -0,0 +1,163 @@
from __future__ import annotations
import tempfile
import unittest
from contextlib import ExitStack
from http.client import HTTPConnection
from pathlib import Path
from unittest.mock import patch
from moli_benchmark.wpt_cross.case_set import enumerate_cases
from moli_benchmark.wpt_cross.server import WptFixtureServer
RESOURCE = "/xhr/resources/inspect-headers.py"
class XhrHeaderFixtureTests(unittest.TestCase):
def setUp(self) -> None:
self.stack = ExitStack()
self.addCleanup(self.stack.close)
self.root = Path(self.stack.enter_context(tempfile.TemporaryDirectory()))
(self.root / "resources").mkdir()
(self.root / "resources/testharness.js").write_text("// testharness")
self.stack.enter_context(patch(
"moli_benchmark.wpt_cross.server._global_ipv6_address", return_value=None
))
def server(self) -> WptFixtureServer:
return self.stack.enter_context(WptFixtureServer(self.root))
def request(
self, port: int, query: str, headers: list[tuple[str, str]],
*, method: str = "GET",
) -> tuple[int, dict[str, str], bytes]:
connection = HTTPConnection("127.0.0.1", port, timeout=2)
try:
connection.putrequest(method, RESOURCE + "?" + query)
for name, value in headers:
connection.putheader(name, value)
connection.endheaders()
response = connection.getresponse()
return (
response.status,
{name.lower(): value for name, value in response.getheaders()},
response.read(),
)
finally:
connection.close()
def test_name_filter_preserves_case_duplicates_whitespace_and_bytes(self) -> None:
server = self.server()
status, headers, body = self.request(server.port, "filter_name=X-CaSe", [
("x-Case", "first"),
("X-Unrelated", "ignored"),
("X-CASE", ""),
("x-cASE", "caf\xe9\xff \t"),
("X-case", "folded\r\n\tvalue"),
])
self.assertEqual(status, 200)
self.assertEqual(body, b"x-Case: first\nX-CASE: \nx-cASE: caf\xe9\xff \t\n"
b"X-case: folded\r\n\tvalue\n")
self.assertEqual(headers["content-type"], "text/plain")
self.assertEqual(headers["content-length"], str(len(body)))
self.assertFalse(any(name.startswith("access-control-") for name in headers))
def test_value_filter_is_exact_and_takes_priority_over_name(self) -> None:
server = self.server()
status, _, body = self.request(
server.port, "filter_value=%E9%FF&filter_name=x-other", [
("X-First", "\xe9\xff"),
("x-second", "\xe9\xff"),
("X-First", "\xe9\xff"),
("X-Different-Case", "\xc9\xff"),
("X-Longer", "\xe9\xff "),
("X-Other", "not-matched"),
]
)
self.assertEqual((status, body), (200, b"X-First,x-second,X-First,"))
def test_query_uses_first_values_and_empty_value_falls_back_to_name(self) -> None:
server = self.server()
request_headers = [("X-First", "match"), ("X-Second", "other")]
for query, expected in (
("", b""),
("filter_name=missing", b""),
("filter_name=x-first&filter_name=x-second", b"X-First: match\n"),
("filter_value=match&filter_value=other", b"X-First,"),
("filter_value=&filter_value=match&filter_name=x-second", b"X-Second: other\n"),
("filter_name=&filter_name=x-first", b""),
("filter_value=missing&filter_name=x-first", b""),
):
with self.subTest(query=query):
status, _, body = self.request(server.port, query, request_headers)
self.assertEqual((status, body), (200, expected))
def test_cors_flag_and_methods_match_upstream(self) -> None:
server = self.server()
cors_headers = {
"access-control-allow-origin": "*",
"access-control-allow-credentials": "true",
"access-control-allow-methods": "GET, POST, PUT, FOO",
"access-control-allow-headers": "x-test, x-foo",
"access-control-expose-headers": (
"x-request-method, x-request-content-type, x-request-query, "
"x-request-content-length"
),
}
for method in ("GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "YO", "FOO"):
for flag in ("", "&cors", "&cors=", "&cors=false"):
with self.subTest(method=method, flag=flag):
status, headers, body = self.request(
server.port, "filter_name=x-test" + flag, [
("X-Test", "value"),
("Origin", "http://example.test"),
("Access-Control-Request-Method", "DELETE"),
("Access-Control-Request-Headers", "x-unexpected"),
], method=method,
)
expected = b"X-Test: value\n"
self.assertEqual((status, body), (200, b"" if method == "HEAD" else expected))
self.assertEqual(headers["content-type"], "text/plain")
self.assertEqual(headers["content-length"], str(len(expected)))
self.assertEqual(
{name: value for name, value in headers.items()
if name.startswith("access-control-")},
cors_headers if flag else {},
)
self.assertFalse(any(name.startswith("x-request-") for name in headers))
def test_header_response_does_not_wait_for_upload(self) -> None:
server = self.server()
for name, value in (("Content-Length", "1000000"), ("Transfer-Encoding", "chunked")):
with self.subTest(framing=name):
# request() sends only headers, leaving the promised body unread.
status, headers, body = self.request(
server.port, "filter_name=" + name, [(name, value)], method="POST"
)
self.assertEqual((status, body), (200, f"{name}: {value}\n".encode()))
self.assertEqual(headers["connection"], "close")
def test_case_selection_allows_only_supported_header_fixture_references(self) -> None:
sources = {
"xhr/absolute.window.js": "fetch('/xhr/resources/inspect-headers.py');",
"xhr/relative.window.js": "fetch('./resources/inspect-headers.py?filter_name=test');",
"xhr/nested/parent.window.js": "fetch('../resources/inspect-headers.py');",
"xhr/unknown.window.js": "fetch('resources/inspect-headers.py'); fetch('resources/unknown.py');",
"xhr/suffix.window.js": "fetch('resources/inspect-headers.py2');",
"xhr/script-suffix.window.js": "fetch('resources/inspect-headers.py.js');",
"xhr/prefix.window.js": "fetch('/wrong/xhr/resources/inspect-headers.py');",
"xhr/wrong-parent.window.js": "fetch('../resources/inspect-headers.py');",
"xhr/wrong-root.window.js": "fetch('inspect-headers.py');",
"xhr/nested/wrong-relative.window.js": "fetch('resources/inspect-headers.py');",
}
for path, source in sources.items():
target = self.root / path
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(source)
selected = enumerate_cases(self.root, dir_prefixes=("xhr",))
self.assertEqual([case.case_path for case in selected], [
"xhr/absolute.window.js?moli-wpt-script=window",
"xhr/nested/parent.window.js?moli-wpt-script=window",
"xhr/relative.window.js?moli-wpt-script=window",
])