fix(sayistay): surface clear error when upstream WAF returns 418 (#23)

Verified 2026-05-03 against a real Chrome browser: POSTs to
/KararlarGenelKurul/DataTablesList consistently return HTTP 418
with the WAF block page "Bilgi Güvenliği Politikaları Gereği
Kısıtlanmıştır", regardless of headers, cookies, CSRF token, or
form payload. The block is server-side at sayistay.gov.tr and
cannot be worked around client-side. The Temyiz Kurulu and Daire
endpoints are unaffected (29k/22k records still return normally).

Detect the 418 + WAF marker in all three search methods and raise
a clear RuntimeError explaining it is an upstream restriction,
instead of the cryptic "Client error '418 I'm a teapot'" that
hides the real situation from MCP clients.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
saidsurucu
2026-05-03 01:41:35 +03:00
co-authored by Claude Opus 4.7
parent ee544dc603
commit ae5d590cca
+26
View File
@@ -48,6 +48,12 @@ class SayistayApiClient:
TEMYIZ_KURULU_ENDPOINT = "/KararlarTemyiz/DataTablesList"
DAIRE_ENDPOINT = "/KararlarDaire/DataTablesList"
# Marker present in the upstream WAF block page (also returns HTTP 418).
# Verified 2026-05-03 against real Chrome — the block targets POSTs to
# the DataTablesList endpoints regardless of headers/cookies/CSRF, so
# we surface a specific error instead of the generic "I'm a teapot".
_WAF_BLOCK_MARKER = "Bilgi Güvenliği Politikaları Gereği Kısıtlanmıştır"
# Page endpoints for session initialization and document access
GENEL_KURUL_PAGE = "/KararlarGenelKurul"
TEMYIZ_KURULU_PAGE = "/KararlarTemyiz"
@@ -141,6 +147,23 @@ class SayistayApiClient:
return enum_value
def _raise_if_waf_blocked(self, response: httpx.Response, endpoint_label: str) -> None:
"""
Sayıştay's upstream WAF returns HTTP 418 with a Turkish HTML block
page for POSTs to the DataTablesList endpoints. This affects every
client (verified with real Chrome on 2026-05-03), so there is no
client-side workaround. Detect it and raise a clear error.
"""
if response.status_code == 418 or self._WAF_BLOCK_MARKER in response.text:
raise RuntimeError(
f"Sayıştay upstream WAF blocked the {endpoint_label} request "
f"(HTTP {response.status_code} from {response.request.url}). "
"This is a server-side restriction at sayistay.gov.tr — affects "
"all clients including a real browser — and cannot be worked "
"around from yargi-mcp. Try again later or contact Sayıştay if "
"the block persists."
)
def _build_datatables_params(self, start: int, length: int, draw: int = 1) -> List[Tuple[str, str]]:
"""Build standard DataTables parameters for all endpoints."""
params = [
@@ -384,6 +407,7 @@ class SayistayApiClient:
data=encoded_data,
headers=headers
)
self._raise_if_waf_blocked(response, "Genel Kurul")
response.raise_for_status()
response_json = response.json()
@@ -443,6 +467,7 @@ class SayistayApiClient:
data=encoded_data,
headers=headers
)
self._raise_if_waf_blocked(response, "Temyiz Kurulu")
response.raise_for_status()
response_json = response.json()
@@ -502,6 +527,7 @@ class SayistayApiClient:
data=encoded_data,
headers=headers
)
self._raise_if_waf_blocked(response, "Daire")
response.raise_for_status()
response_json = response.json()