"""http_request — raw HTTP via httpx."""
from __future__ import annotations
import json
from typing import Any
import httpx
_TIMEOUT = 30.0
async def http_request(
method: str,
url: str,
headers: dict[str, str] | None = None,
body: dict[str, Any] | None = None,
params: dict[str, str] | None = None,
) -> dict[str, Any]:
"""Make an HTTP request. Returns dict with success, output, error, metadata."""
headers = headers or {}
try:
async with httpx.AsyncClient(timeout=_TIMEOUT, follow_redirects=True) as client:
response = await client.request(
method=method.upper(),
url=url,
headers=headers,
json=body,
params=params,
)
try:
body_repr = json.dumps(response.json(), ensure_ascii=False, indent=2)
except Exception:
body_repr = response.text[:4096]
output = f"Status: {response.status_code}\n\n{body_repr}"
return {
"success": response.is_success,
"output": output,
"error": None if response.is_success else f"HTTP {response.status_code}",
"metadata": {"status_code": response.status_code, "headers": dict(response.headers)},
}
except httpx.TimeoutException:
return {
"success": False,
"output": f"Request timed out after {_TIMEOUT}s",
"error": "timeout",
"metadata": {},
}
except Exception as e:
return {
"success": False,
"output": f"Request failed: {e}",
"error": str(e),
"metadata": {},
}