HTTP Content Negotiation & Decompression
urllib / http_request never sets Accept-Encoding and never decodes a
Content-Encoding response, so a body from a server that compresses arrives
raw; there was also no quality-value parser. This adds Accept /
Accept-Encoding builders, a q-value parser, and gzip / deflate decoding.
Pure standard library (gzip / zlib); imports no PySide6. Brotli is
deliberately excluded (not stdlib). Every function is pure, so it is fully
deterministic in CI.
Headless API
from je_auto_control import (
build_accept, build_accept_encoding, negotiated_call,
parse_quality_values, decode_body, build_call,
)
call = negotiated_call(
build_call(url),
accept=build_accept([("application/json", 1.0), ("text/html", 0.8)]),
accept_encoding=build_accept_encoding(),
)
# ... perform the call, then:
body = decode_body(response["headers"], raw_bytes)
ranked = parse_quality_values("text/html;q=0.8, application/json")
# [("application/json", 1.0), ("text/html", 0.8)]
build_accept turns media types or (type, q) pairs into an Accept
header; build_accept_encoding defaults to gzip, deflate.
parse_quality_values parses an Accept / Accept-Encoding header into
(token, q) pairs sorted by quality (ties keep their order). decode_body
decompresses a response body according to its Content-Encoding (gzip /
deflate, including raw deflate, plus identity), raising ValueError
for anything unsupported. negotiated_call adds the negotiation headers to a
build_call dict.
Executor commands
AC_decode_body decodes a base64 body_base64 per its headers and
returns {body_base64, text}; AC_parse_quality_values returns
{values}. Both are exposed as MCP tools (ac_decode_body /
ac_parse_quality_values) and as Script Builder commands under Data.