Backend

A backend is the adapter layer that lets ahttp_client drive different third-party HTTP client libraries through one common interface. A backend is never instantiated directly; the HTTP client class is passed to a session instead, and the matching backend is selected automatically.

import aiohttp
import httpx

# Selects AiohttpBackend
aiohttp_service = GithubService("https://api.github.com", aiohttp.ClientSession)

# Selects HttpXAsyncSession
httpx_service = GithubService("https://api.github.com", httpx.AsyncClient)

Supported Backends

Library

Session class

Backend class

Extra dependency

aiohttp

aiohttp.ClientSession

ahttp_client.backend.AiohttpBackend

pip install aiohttp

httpx (async)

httpx.AsyncClient

ahttp_client.backend.HttpXAsyncSession

pip install httpx

httpx (sync)

httpx.Client

ahttp_client.backend.HttpXSyncSession

pip install httpx

requests (sync)

requests.Session

ahttp_client.backend.RequestsBackend

pip install requests

AsyncSession takes aiohttp.ClientSession, httpx.AsyncClient, or any other registered asynchronous session class. Session takes httpx.Client, requests.Session, or any other registered synchronous session class.

Note

An optional dependency (aiohttp, httpx, or requests) that is not installed is simply skipped: ahttp_client.backend only exports the backends whose third-party package is importable.

How Backend Selection Works

BaseBackend keeps a registry mapping third-party session classes to their backend classes. A concrete backend adds itself to that registry automatically, through __init_subclass__, as soon as both session_cls and response_cls are defined on it.

When a session such as AsyncSession(base_url, aiohttp.ClientSession) is created, it calls AsyncBackend.from_session(aiohttp.ClientSession, base_url=base_url, **kwargs), which looks up the registered backend for that session class and instantiates it. This is why the session=… argument on AsyncSession/Session is simply the third-party client class, not a backend instance.

Writing a Custom Backend

Subclass AsyncBackend for an asynchronous client, or SyncBackend for a synchronous one, and set session_cls/response_cls on it. The remaining work is implementing a handful of abstract methods:

  • get_request_kwargs turns a RequestCore into that client’s request keyword arguments.

  • response_status, response_headers, response_url, response_data, response_text, response_json, and response_closed read the status code, headers, URL, body, and closed state off that client’s response object.

  • response_close and session_close/session_closed handle closing a response and the session itself.

  • session_request, session_get, session_post, session_options, session_delete, session_patch, and session_put issue each HTTP method against the underlying session.

 1from ahttp_client.backend import AsyncBackend
 2
 3class MyClientBackend(AsyncBackend):
 4    session_cls = my_client.Session
 5    response_cls = my_client.Response
 6
 7    def get_request_kwargs(self, request_obj):
 8        ...
 9
10    def response_status(self, response_obj) -> int:
11        return response_obj.status_code
12
13    # ... remaining abstract methods

Once MyClientBackend is imported, AsyncSession(base_url, my_client.Session) resolves to it automatically; no further registration is required.

Reference

class BaseBackend

Base adapter for a supported HTTP client library.

A backend creates the client session, converts RequestCore values to client-specific keyword arguments, and exposes a common response interface. Subclasses that define both session_cls and response_cls are registered automatically.

classmethod from_session(session: type[Any], **kwargs: Any) → _BackendT

Create the backend registered for an HTTP client session class.

Parameters:
  • session (type) – Supported HTTP client session class.

  • **kwargs – Keyword arguments forwarded to the backend constructor.

Raises:

TypeError – If session is not registered with a backend.

abstractmethod get_request_kwargs(request_obj: RequestCore[Any, Any]) → dict[str, Any]

Convert a request descriptor into client-specific request arguments.

abstractmethod response_close(response_obj: Any) → None | Awaitable[None]

Close a client response object.

abstractmethod response_closed(response_obj: Any) → bool | None

Return response close state, or None if it is unavailable.

abstractmethod response_data(response_obj: Any) → bytes

Return the response body as bytes.

abstractmethod response_headers(response_obj: Any) → dict[str, Any]

Return response headers as a dictionary.

abstractmethod response_json(response_obj: Any, json_parser: Callable[..., Any] | None = None, json_kwargs: dict[str, Any] | None = None) → Any | None

Parse the response body as JSON using an optional custom parser.

abstractmethod response_status(response_obj: Any) → int

Return the HTTP status code from a client response.

abstractmethod response_text(response_obj: Any) → str

Return the response body decoded as text.

abstractmethod response_url(response_obj: Any) → str

Return the URL associated with a client response.

abstract property session_closed: bool

Return whether the underlying HTTP client session is closed.

class AsyncBackend

Bases: BaseBackend, ABC

Base adapter contract for asynchronous HTTP client libraries.

async pre_read_response(response_obj: Any) → None

Read a response before it is exposed through Response.

Backends that require eager reads can override this method.

abstractmethod async session_close() → None

Close the underlying asynchronous HTTP client session.

abstractmethod async session_delete(path: str, **kwargs: Any) → Any

Make an asynchronous DELETE request.

abstractmethod async session_get(path: str, **kwargs: Any) → Any

Make an asynchronous GET request.

abstractmethod async session_options(path: str, **kwargs: Any) → Any

Make an asynchronous OPTIONS request.

abstractmethod async session_patch(path: str, **kwargs: Any) → Any

Make an asynchronous PATCH request.

abstractmethod async session_post(path: str, **kwargs: Any) → Any

Make an asynchronous POST request.

abstractmethod async session_put(path: str, **kwargs: Any) → Any

Make an asynchronous PUT request.

abstractmethod async session_request(method: str, path: str, **kwargs: Any) → Any

Make an asynchronous HTTP request with the given method and path.

class SyncBackend

Bases: BaseBackend, ABC

Base adapter contract for synchronous HTTP client libraries.

abstractmethod session_close() → None

Close the underlying synchronous HTTP client session.

abstractmethod session_delete(path: str, **kwargs: Any) → Any

Make a synchronous DELETE request.

abstractmethod session_get(path: str, **kwargs: Any) → Any

Make a synchronous GET request.

abstractmethod session_options(path: str, **kwargs: Any) → Any

Make a synchronous OPTIONS request.

abstractmethod session_patch(path: str, **kwargs: Any) → Any

Make a synchronous PATCH request.

abstractmethod session_post(path: str, **kwargs: Any) → Any

Make a synchronous POST request.

abstractmethod session_put(path: str, **kwargs: Any) → Any

Make a synchronous PUT request.

abstractmethod session_request(method: str, path: str, **kwargs: Any) → Any

Make a synchronous HTTP request with the given method and path.

class AiohttpBackend

Bases: AsyncBackend

Backend adapter for aiohttp.ClientSession.

Requires the aiohttp package (pip install aiohttp). Registered for aiohttp.ClientSession and wraps aiohttp.ClientResponse as its response type.

class HttpXAsyncSession

Bases: AsyncBackend, CommonHttpXBackend

Backend adapter for httpx.AsyncClient.

Requires the httpx package (pip install httpx). Registered for httpx.AsyncClient and used when a session is created with AsyncSession(base_url, httpx.AsyncClient).

class HttpXSyncSession

Bases: SyncBackend, CommonHttpXBackend

Backend adapter for httpx.Client.

Requires the httpx package (pip install httpx). Registered for httpx.Client and used when a session is created with Session(base_url, httpx.Client).

class RequestsBackend

Bases: SyncBackend

Backend adapter for requests.Session.

Requires the requests package (pip install requests). Registered for requests.Session and used when a session is created with Session(base_url, requests.Session).

requests.Response has no built-in closed state, so this backend tracks it manually via an internal _closed flag that is only ever set by session_close().