Introduction¶
ahttp-client is a Python package that provides concise and intuitive asynchronous (and synchronous) HTTP requests using annotated types and @decorators.
Key Features
Declare HTTP endpoints using request or the get, post, put, patch, delete, and options decoration methods.
Manage HTTP components, such as the path, query, header, or body values, using annotated types (see HTTP Component).
Customize the request lifecycle before and after an HTTP call, with optional retry and exponential backoff (see Pre Hooking / Post Hooking and Retry).
Swap between aiohttp, httpx, and requests as pluggable backends without changing how a service is declared (see Backend).
Serialize typed request models and deserialize responses using registered codecs for dataclasses, pydantic, or marshmallow (see Serialization).
Raise a typed HTTPException for 4xx/5xx responses (see Exception).
Installation¶
ahttp-client requires Python 3.11 or later. Install the extra for the HTTP client library a service will use.
pip install "ahttp-client[aiohttp]"
pip install "ahttp-client[httpx]"
pip install "ahttp-client[requests]"
Add the pydantic extra to serialize and deserialize pydantic.BaseModel instances (see Serialization).
pip install "ahttp-client[aiohttp,pydantic]"
Getting Started¶
Two session base classes cover both styles of client:
Style |
Supported client classes |
Session class |
|---|---|---|
Async |
aiohttp.ClientSession, httpx.AsyncClient |
AsyncSession |
Sync |
requests.Session, httpx.Client |
Session |
Asynchronous Client¶
Implement a GithubService class extended with ahttp_client.AsyncSession. Then, create a list_repositories method using a request decorator.
A user argument defines an HTTP component (Path) through an annotated type.
class GithubService(AsyncSession):
def __init__(self):
super().__init__("https://api.github.com", aiohttp.ClientSession)
@request("GET", "/users/{user}/repos")
async def list_repositories(
self, response: Response, user: Annotated[str, Path]
) -> list[dict[str, Any]]:
return response.json()
Using the asynchronous context manager (async with), create a GithubService instance.
async with GithubService() as service:
result = await service.list_repositories(user="gunyu1019")
print(result)
The client session inside GithubService closes automatically once the asynchronous context manager exits.
Synchronous Client¶
For a synchronous service, extend Session instead and use a regular function with requests.Session or httpx.Client.
class GithubService(Session):
def __init__(self):
super().__init__("https://api.github.com", requests.Session)
@request("GET", "/users/{user}/repos")
def list_repositories(
self, response: Response, user: Annotated[str, Path]
) -> list[dict[str, Any]]:
return response.json()
with GithubService() as service:
result = service.list_repositories(user="gunyu1019")
print(result)
The client session inside GithubService closes automatically once the with block exits.