Introduction

https://img.shields.io/pypi/v/ahttp-client?style=flat https://img.shields.io/pypi/dm/ahttp-client?style=flat https://img.shields.io/pypi/l/ahttp-client?style=flat

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.