"""Every HTTP input form -> one Request: raw requests (CSIC-style text), access-log lines (nginx/apache combined), bare URLs. Parameters are extracted from the query, a form, JSON or multipart body and cookies; the model text is built from the canonical form of each part (canon.py). The text is what every tier judges (playbook signatures, the A22 SQL-context tier, the HTTP model), and the Go fast path builds the very same text (go/dibaguard/canon.go, proven by the canon_parity.json fixture of tests/test_parity.py) - so the Python-side defences hold in a Go deployment and in its sidecar too (V-08). Nothing is dropped from judgement silently (V-05, V-06, V-07): every occurrence of a duplicate JSON key, every multipart field, every value of a repeated header, every field and the whole of a value are written into the text while a judging budget lasts (MAX_TEXT characters); past it, only the parts that can carry a payload are written (_keep, up to EXTRA_TEXT more), and whatever still does not fit is counted in an `x:oversized=` part, which the SQL-context tier answers with a soft alarm (sqlctx.analyse) - a request too large to judge is never simply allowed. The work stays linear in the request size and bounded: at most MAX_FIELDS fields are canonicalised one by one (the rest as one blob), a value is decoded up to canon.MAX_LEN characters, the text never exceeds MAX_TEXT + EXTRA_TEXT.""" from __future__ import annotations import json import re from dataclasses import dataclass, field from urllib.parse import urlsplit from dibaguard.http.canon import MAX_LEN, canon_views COMBINED = re.compile(r'^(?P\S+) \S+ \S+ \[(?P