Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

ahttp-client

PyPI - Version PyPI - Downloads PyPI - License

ahttp-client is a decorator-based HTTP client framework that maps typed function parameters to HTTP requests.

Key Features

  • Declare HTTP endpoints using @request or the @get, @post, @put, @patch, @delete, and @options decoration methods.
  • Use typing.Annotated to set HTTP parameters such as the path, query, header, or body values.
  • Serialize typed request models and deserialize responses using registered codecs.
  • Customize the request lifecycle using before_hook and after_hook decorators.
  • Reduce boilerplate code when using HTTP client packages such as aiohttp, httpx, and requests.

Installation

Install the extra for the HTTP client library you want to use. Python 3.11 or later is required.

pip install "ahttp-client[aiohttp]"
pip install "ahttp-client[httpx]"
pip install "ahttp-client[requests]"

Include the pydantic extra to serialize and deserialize Pydantic models.

pip install "ahttp-client[aiohttp,pydantic]"

Quick start

Style Supported client classes Session class
Async aiohttp.ClientSession, httpx.AsyncClient AsyncSession
Sync requests.Session, httpx.Client Session

Asynchronous Client

Declare a service by extending AsyncSession, then decorate coroutine methods with an HTTP method and path. Annotated parameters determine where values are placed in the request.

import asyncio
from typing import Annotated, Any

import aiohttp

from ahttp_client import AsyncSession, Path, Response, get


class GitHubService(AsyncSession):
    def __init__(self):
        super().__init__("https://api.github.com", aiohttp.ClientSession)

    @get("/users/{user}/repos")
    async def list_repositories(
        self, response: Response, user: Annotated[str, Path]
    ) -> list[dict[str, Any]]:
        return response.json()


async def main():
    async with GitHubService() as service:
        repositories = await service.list_repositories(user="gunyu1019")
        print(repositories)


asyncio.run(main())

AsyncSession closes its underlying HTTP client when the async with block ends. Decorated responses are also closed automatically after the handler returns.

Synchronous Client

Use Session and a regular function with requests.Session or httpx.Client.

from typing import Annotated, Any

import requests

from ahttp_client import Path, Response, Session, get


class GitHubService(Session):
    def __init__(self):
        super().__init__("https://api.github.com", requests.Session)

    @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:
    repositories = service.list_repositories(user="gunyu1019")
    print(repositories)

Request components

Use Annotated to describe dynamic request values.

from typing import Annotated

from ahttp_client import BodyJson, Header, Path, Query, Response, post


class UserService(AsyncSession):
    @post("/users/{user_id}")
    async def update_user(
        self,
        response: Response,
        user_id: Annotated[int, Path],
        verbose: Annotated[bool, Query],
        authorization: Annotated[str, Header.custom_name("Authorization")],
        display_name: Annotated[str, BodyJson.custom_key("profile.displayName")],
    ) -> dict:
        return response.json()
Component Request location
Path A {placeholder} in the path
Query Query string
Header Request header
BodyJson JSON body field; supports nested keys
BodyForm URL-encoded or multipart form field
Body Complete raw or JSON request body

Set directly_response=True on a request (or a session) when you need the Response object itself instead of running the decorated handler. In that case, close it yourself with await response.async_close() for async clients or response.close() for sync clients.

Model serialization

Registered codecs can convert a complete Body parameter before transport and validate a direct response from its return annotation. When Pydantic is installed, BaseModel types and nested model containers are supported automatically.

Use @serialize and @deserialize to pass codec options. If the model argument is omitted, the request body and return annotations select the codec after the request decorator is applied.

from typing import Annotated

from pydantic import BaseModel

from ahttp_client import AsyncSession, Body, post
from ahttp_client.serializer import deserialize, serialize


class CreateUser(BaseModel):
    name: str
    nickname: str | None = None


class User(BaseModel):
    id: int
    name: str


class UserService(AsyncSession):
    @post("/users", directly_response=True)
    @serialize(exclude_none=True)
    @deserialize(strict=True)
    async def create_user(
        self,
        user: Annotated[CreateUser, Body],
    ) -> User:
        ...

In this example, the request body is produced with BaseModel.model_dump(mode="json", exclude_none=True), and the JSON response is validated as User. Because directly_response=True selects deserialized mode from the registered return type, the decorated method body is not executed. Pass a model explicitly, such as @serialize(CreateUser), when it cannot be inferred from an annotation.

Hooks

Attach a hook to a decorated request to modify it before dispatch or transform its result afterward. Async requests require async hooks; sync requests require regular functions.

class GitHubService(AsyncSession):
    @get("/user")
    async def current_user(self, response: Response) -> dict:
        return response.json()

    @current_user.before_hook
    async def add_authorization(self, request, path):
        request.headers["Authorization"] = "Bearer <token>"
        return request, path

Override before_request() or after_request() on AsyncSession or Session to apply the same behavior to every request in a service.

Documentation

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ahttp_client-2.0.0b2.tar.gz (38.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ahttp_client-2.0.0b2-py3-none-any.whl (47.0 kB view details)

Uploaded Python 3

File details

Details for the file ahttp_client-2.0.0b2.tar.gz.

File metadata

  • Download URL: ahttp_client-2.0.0b2.tar.gz
  • Upload date:
  • Size: 38.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for ahttp_client-2.0.0b2.tar.gz
Algorithm Hash digest
SHA256 07e327853eaab491278ed075f8b999a7728adc7d0dbc2345bb99d7cc6b772d6c
MD5 fc80532d421079e63a6e218c39f3378c
BLAKE2b-256 d6a81da70773534a61e52fedc935ed2bbad818ff4c4281446eadab861aef3e7f

See more details on using hashes here.

Provenance

The following attestation bundles were made for ahttp_client-2.0.0b2.tar.gz:

Publisher: deploy.yml on gunyu1019/ahttp-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ahttp_client-2.0.0b2-py3-none-any.whl.

File metadata

  • Download URL: ahttp_client-2.0.0b2-py3-none-any.whl
  • Upload date:
  • Size: 47.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for ahttp_client-2.0.0b2-py3-none-any.whl
Algorithm Hash digest
SHA256 cb031dd40464a0a932794773093d618c98197a7e5f4176d1a903a70a902b30e8
MD5 2a228299b8bdddc1ed5820c8a2865f1b
BLAKE2b-256 878269c57033ca4409e0788b7f21dc448cd6e196e45d678bdaced9b1b7bab70f

See more details on using hashes here.

Provenance

The following attestation bundles were made for ahttp_client-2.0.0b2-py3-none-any.whl:

Publisher: deploy.yml on gunyu1019/ahttp-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

2.0.0

2 files

This release

2.0.0b2 This release

2 files

1.1.0

2 files

1.0.5

2 files

1.0.4

2 files

1.0.3

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page