9fd0ca9cac
Infra: cache_to_file, cache_to_sqlite, http_download_file, http_get_json, http_post_json, read_file_with_encoding, safe_extract_zip, scan_directory, setup_logger, normalize_zip_filenames. Tipos: 30+ tipos core (agent_action, context, task, message, parse_result...), 6 tipos datascience (entity_candidate, extraction_result...), 2 tipos infra. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
59 lines
1.8 KiB
Python
59 lines
1.8 KiB
Python
"""GET request JSON — HTTP client sin dependencias externas."""
|
|
|
|
import json
|
|
import urllib.error
|
|
import urllib.parse
|
|
import urllib.request
|
|
|
|
|
|
def http_get_json(
|
|
url: str,
|
|
headers: dict[str, str] | None = None,
|
|
params: dict[str, str] | None = None,
|
|
timeout: float = 30.0,
|
|
) -> dict:
|
|
"""Realiza un GET request y parsea la respuesta como JSON.
|
|
|
|
Agrega automaticamente el header ``Accept: application/json``.
|
|
Si el status es >= 400 lanza RuntimeError con status code, url y
|
|
los primeros 200 caracteres del body para facilitar el debugging.
|
|
|
|
Args:
|
|
url: URL del endpoint.
|
|
headers: Headers HTTP adicionales. Se fusionan con Accept por defecto.
|
|
params: Query string params. Se serializa con urllib.parse.urlencode.
|
|
timeout: Segundos maximo de espera (default 30).
|
|
|
|
Returns:
|
|
Respuesta parseada como dict o list.
|
|
|
|
Raises:
|
|
RuntimeError: Si status >= 400 o si el body no es JSON valido.
|
|
"""
|
|
if params:
|
|
url = f"{url}?{urllib.parse.urlencode(params)}"
|
|
|
|
all_headers: dict[str, str] = {"Accept": "application/json"}
|
|
if headers:
|
|
all_headers.update(headers)
|
|
|
|
req = urllib.request.Request(url, headers=all_headers, method="GET")
|
|
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
raw = resp.read()
|
|
except urllib.error.HTTPError as e:
|
|
body_preview = e.read(200).decode("utf-8", errors="replace")
|
|
short_url = url[:100] if len(url) > 100 else url
|
|
raise RuntimeError(
|
|
f"http_get_json: HTTP {e.code} at {short_url!r} — {body_preview}"
|
|
) from e
|
|
|
|
try:
|
|
return json.loads(raw)
|
|
except json.JSONDecodeError as e:
|
|
preview = raw[:200].decode("utf-8", errors="replace")
|
|
raise RuntimeError(
|
|
f"http_get_json: response is not valid JSON — {preview}"
|
|
) from e
|