"""Wire contracts for static UI caching: ETag, 304, gzip, immutable, symlink.
These go through a real `ThreadingHTTPServer` rather than a stubbed `_send`.
304-without-a-body and gzip Content-Length are properties of the status line
and the bytes on the socket; a captured `_send` call cannot see them.
"""
from __future__ import annotations
import gzip
import http.client
import json
import threading
from pathlib import Path
import pytest
from openai4s.config import Config, LLMConfig
from openai4s.server import gateway as gateway_mod
from openai4s.server import local_auth
from openai4s.server.security_headers import security_headers
from tests._ports import bound_gateway_server
_PAYLOAD = ("static-cache-payload\n" * 80).encode("ascii") # >1KB, gzip-friendly
assert len(_PAYLOAD) > 1024
class _Hub:
def emitter(self, root_frame_id):
return lambda event: None
def broadcast(self, root_frame_id, event):
return None
def _write(webui: Path, rel: str, data: bytes) -> Path:
path = webui / rel
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(data)
return path
@pytest.fixture()
def static_daemon(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
"""Loopback gateway whose `/static/` tree is a fixture, not the real webui."""
webui = tmp_path / "webui"
webui.mkdir()
_write(webui, "index.html", b"
fixture\n" + _PAYLOAD)
_write(
webui,
"dist/index.html",
b"dist-fixture\n" + _PAYLOAD,
)
_write(webui, "app.js", _PAYLOAD)
_write(webui, "tiny.js", b"ok")
_write(webui, "style.css", _PAYLOAD)
_write(webui, "main.8617f334.js", _PAYLOAD)
_write(webui, "622.365fdd8e.chunk.css", _PAYLOAD)
_write(webui, "AnthropicSans-Roman-Variable-CFxw3nG7.woff2", _PAYLOAD[:400])
_write(webui, "plain.bin", _PAYLOAD)
_write(webui, "vendor/ketcher/index.html", b"ketcher\n" + _PAYLOAD)
monkeypatch.setattr(gateway_mod, "WEBUI_DIR", webui)
httpd, port = bound_gateway_server()
cfg = Config(
data_dir=tmp_path / "data",
llm=LLMConfig(provider="deepseek", api_key="test-key"),
max_turns=3,
host="127.0.0.1",
port=port,
)
cfg.ensure_dirs()
runner = gateway_mod.SessionRunner(cfg, _Hub(), start_idle_sweeper=False)
handler_cls = gateway_mod.make_handler(cfg, _Hub(), runner)
httpd.RequestHandlerClass = handler_cls
thread = threading.Thread(target=httpd.serve_forever, daemon=True)
thread.start()
token = local_auth.load_or_mint(cfg.data_dir)
try:
yield {
"port": port,
"token": token,
"webui": webui,
"handler_cls": handler_cls,
"outside": tmp_path / "outside.txt",
}
finally:
httpd.shutdown()
httpd.server_close()
thread.join(timeout=5)
try:
runner.close()
except Exception: # noqa: BLE001 - teardown must not mask a failure
pass
def _get(
port: int,
path: str,
token: str,
extra: dict[str, str] | None = None,
) -> tuple[int, dict[str, str], bytes]:
headers = {local_auth.TOKEN_HEADER: token}
if extra:
headers.update(extra)
conn = http.client.HTTPConnection("127.0.0.1", port, timeout=10)
try:
conn.request("GET", path, headers=headers)
resp = conn.getresponse()
body = resp.read()
hdrs = {key.lower(): value for key, value in resp.getheaders()}
return resp.status, hdrs, body
finally:
conn.close()
def _security_keys() -> set[str]:
return {key.lower() for key in security_headers()}
@pytest.mark.parametrize(
"name, expected",
[
("main.8617f334.js", True),
("622.365fdd8e.chunk.css", True),
("159.6bd8317f.chunk.js", True),
("AnthropicSans-Roman-Variable-CFxw3nG7.woff2", True),
("AnthropicSerif-Roman-Variable-C-BHYa_K.woff2", True),
("AnthropicMono-Roman-Web-B88FVziN.woff2", True),
("AnthropicMono-Italic-Web-DHGc3er-.woff2", True),
("anthropicons-variable-DICoRAgs.woff2", True),
("app.js", False),
("style.css", False),
("index.html", False),
("theme-bootstrap.js", False),
("scientific_renderers.js", False),
("3Dmol-min.js", False),
("favicon_anim_64.gif", False),
("ketcher-page.js", False),
],
)
def test_fingerprint_names_are_the_hashed_vendor_assets(name: str, expected: bool):
assert gateway_mod._is_fingerprinted_name(name) is expected
def test_index_html_defers_body_scripts_and_preloads_roman_fonts():
html = (Path(gateway_mod.WEBUI_DIR) / "index.html").read_text(encoding="utf-8")
assert '' in html
assert '' in html
for href in (
"/static/vendor/fonts/AnthropicSans-Roman-Variable-CFxw3nG7.woff2",
"/static/vendor/fonts/AnthropicSerif-Roman-Variable-C-BHYa_K.woff2",
"/static/vendor/fonts/AnthropicMono-Roman-Web-B88FVziN.woff2",
):
assert (
f'rel="preload" href="{href}" as="font" type="font/woff2" crossorigin'
in html
)
def test_etag_miss_then_hit_is_empty_304_with_security_headers(static_daemon):
port, token = static_daemon["port"], static_daemon["token"]
status, hdrs, body = _get(port, "/static/app.js", token)
assert status == 200
assert body == _PAYLOAD
etag = hdrs["etag"]
assert etag.startswith("W/")
assert "-gz" not in etag
assert hdrs["cache-control"] == "no-cache"
miss, miss_hdrs, miss_body = _get(
port, "/static/app.js", token, {"If-None-Match": 'W/"deadbeef-1"'}
)
assert miss == 200
assert miss_body == _PAYLOAD
assert miss_hdrs["etag"] == etag
hit, hit_hdrs, hit_body = _get(
port, "/static/app.js", token, {"If-None-Match": etag}
)
assert hit == 304
assert hit_body == b""
assert hit_hdrs.get("content-length") in ("0", None)
assert hit_hdrs["etag"] == etag
for key in _security_keys():
assert key in hit_hdrs, f"304 dropped {key}"
script_src = (
hit_hdrs["content-security-policy"].split("script-src", 1)[-1].split(";", 1)[0]
)
assert "'unsafe-eval'" not in script_src
assert "'unsafe-inline'" not in script_src
def test_gzip_negotiation_vary_and_identity_fallback(static_daemon):
port, token = static_daemon["port"], static_daemon["token"]
identity_status, identity_hdrs, identity_body = _get(port, "/static/app.js", token)
assert identity_status == 200
assert identity_body == _PAYLOAD
assert "content-encoding" not in identity_hdrs
assert identity_hdrs["vary"] == "Accept-Encoding"
identity_etag = identity_hdrs["etag"]
assert not identity_etag.endswith('-gz"')
gz_status, gz_hdrs, gz_body = _get(
port, "/static/app.js", token, {"Accept-Encoding": "gzip"}
)
expected = gzip.compress(_PAYLOAD, compresslevel=6, mtime=0)
assert gz_status == 200
assert gz_hdrs["content-encoding"] == "gzip"
assert gz_hdrs["vary"] == "Accept-Encoding"
assert gz_body == expected
assert len(gz_body) < len(_PAYLOAD)
gz_etag = gz_hdrs["etag"]
assert gz_etag.endswith('-gz"')
assert gz_etag != identity_etag
# A gzip ETag is a different representation; identity must not 304 on it.
cross, _, cross_body = _get(
port, "/static/app.js", token, {"If-None-Match": gz_etag}
)
assert cross == 200
assert cross_body == _PAYLOAD
gz_hit, gz_hit_hdrs, gz_hit_body = _get(
port,
"/static/app.js",
token,
{"Accept-Encoding": "gzip", "If-None-Match": gz_etag},
)
assert gz_hit == 304
assert gz_hit_body == b""
assert gz_hit_hdrs["etag"] == gz_etag
assert gz_hit_hdrs["content-encoding"] == "gzip"
assert gz_hit_hdrs["vary"] == "Accept-Encoding"
for key in _security_keys():
assert key in gz_hit_hdrs
refused, refused_hdrs, refused_body = _get(
port, "/static/app.js", token, {"Accept-Encoding": "gzip;q=0"}
)
assert refused == 200
assert refused_body == _PAYLOAD
assert "content-encoding" not in refused_hdrs
tiny_status, tiny_hdrs, tiny_body = _get(
port, "/static/tiny.js", token, {"Accept-Encoding": "gzip"}
)
assert tiny_status == 200
assert tiny_body == b"ok"
assert "content-encoding" not in tiny_hdrs
assert "vary" not in tiny_hdrs
bin_status, bin_hdrs, bin_body = _get(
port, "/static/plain.bin", token, {"Accept-Encoding": "gzip"}
)
assert bin_status == 200
assert bin_body == _PAYLOAD
assert "content-encoding" not in bin_hdrs
assert "vary" not in bin_hdrs
def test_immutable_cache_control_is_only_for_fingerprint_names(static_daemon):
port, token = static_daemon["port"], static_daemon["token"]
hashed_js = _get(port, "/static/main.8617f334.js", token)
hashed_css = _get(port, "/static/622.365fdd8e.chunk.css", token)
font = _get(port, "/static/AnthropicSans-Roman-Variable-CFxw3nG7.woff2", token)
app = _get(port, "/static/app.js", token)
css = _get(port, "/static/style.css", token)
index = _get(port, "/", token)
for status, hdrs, _body in (hashed_js, hashed_css, font):
assert status == 200
assert hdrs["cache-control"] == "public, max-age=31536000, immutable"
for status, hdrs, _body in (app, css, index):
assert status == 200
assert hdrs["cache-control"] == "no-cache"
_, hit_hdrs, hit_body = _get(
port,
"/static/main.8617f334.js",
token,
{"If-None-Match": hashed_js[1]["etag"]},
)
assert hit_body == b""
assert hit_hdrs["cache-control"] == "public, max-age=31536000, immutable"
for key in _security_keys():
assert key in hit_hdrs
def test_files_over_the_stream_threshold_still_etag_and_304(
static_daemon, monkeypatch: pytest.MonkeyPatch
):
monkeypatch.setattr(gateway_mod, "_STATIC_STREAM_BYTES", 32)
port, token = static_daemon["port"], static_daemon["token"]
webui = static_daemon["webui"]
_write(webui, "blob.bin", b"x" * 64)
_write(webui, "main.aaaaaaaa.js", b"y" * 64)
streamed: list[str] = []
orig = static_daemon["handler_cls"]._stream_file
def _wrap(self, path, ctype, extra=None, security=None):
streamed.append(Path(path).name)
return orig(self, path, ctype, extra=extra, security=security)
monkeypatch.setattr(static_daemon["handler_cls"], "_stream_file", _wrap)
status, hdrs, body = _get(port, "/static/blob.bin", token)
assert status == 200
assert body == b"x" * 64
assert "blob.bin" in streamed
etag = hdrs["etag"]
hit, hit_hdrs, hit_body = _get(
port, "/static/blob.bin", token, {"If-None-Match": etag}
)
assert hit == 304
assert hit_body == b""
for key in _security_keys():
assert key in hit_hdrs
js_status, js_hdrs, js_body = _get(port, "/static/main.aaaaaaaa.js", token)
assert js_status == 200
assert js_body == b"y" * 64
assert "main.aaaaaaaa.js" in streamed
assert js_hdrs["cache-control"] == "public, max-age=31536000, immutable"
def test_symlink_escape_is_forbidden_after_realpath(static_daemon):
port, token = static_daemon["port"], static_daemon["token"]
outside = static_daemon["outside"]
outside.write_bytes(b"should-not-leak")
link = static_daemon["webui"] / "leak.js"
link.symlink_to(outside)
status, hdrs, body = _get(port, "/static/leak.js", token)
assert status == 403
payload = json.loads(body.decode("utf-8"))
assert payload["error"] == "forbidden"
assert b"should-not-leak" not in body
assert "content-security-policy" in hdrs
parent = _get(port, "/static/../outside.txt", token)
assert parent[0] == 403
assert b"should-not-leak" not in parent[2]
missing = _get(port, "/static/no-such-file.js", token)
assert missing[0] == 404
assert json.loads(missing[2].decode("utf-8"))["error"] == "not found"