import json
from typing import Any
[docs]
class Response:
"""HTTP response object.
Contains the status code, headers, body, and timing information from an
HTTP response. Provides convenience methods for processing the response.
"""
def __init__(self, status_code: int, headers: dict, body: bytes, elapsed: float = None) -> None:
"""Initialize an HTTP Response.
Args:
status_code (int): HTTP status code
headers (dict): HTTP response headers
body (bytes): Response body as bytes
elapsed (float, optional): Elapsed time in seconds. Defaults to None.
"""
self.status_code = status_code
self.headers = headers
self.body = body
self.elapsed = elapsed # seconds (float)
@property
def elapsed_time(self) -> int | None:
"""Get the elapsed time in milliseconds.
Returns:
int | None: Elapsed time in milliseconds, or None if not available
"""
if self.elapsed is None:
return None
return int(self.elapsed * 1000)
[docs]
def text(self) -> str:
"""Get the response body as text.
Returns:
str: Response body decoded as UTF-8 string
"""
return self.body.decode("utf-8")
[docs]
def json(self) -> Any:
"""Parse the response body as JSON.
Returns:
Any: Parsed JSON object
Raises:
ValueError: If response body is not valid JSON
"""
try:
return json.loads(self.body)
except Exception as e:
raise ValueError("Invalid JSON response")
[docs]
def raise_for_status(self) -> None:
"""Raise an exception if the status code indicates an error.
Raises an exception for 4xx and 5xx status codes.
Raises:
Exception: If status code is 400-599
"""
# same method as requests but it seems with different behavior
if 400 <= self.status_code < 600:
raise Exception(f"HTTP Error: {self.status_code}")
[docs]
def is_ok(self) -> bool:
"""Check if the response status code indicates success (2xx).
Returns:
bool: True if status code is 200-299, False otherwise
"""
return 200 <= self.status_code < 300
def __repr__(self) -> str:
"""Return a string representation of the response.
Returns:
str: String representation includes status code, headers, and body
"""
return f"<Response [{self.status_code}, {self.headers}, {self.body}]"