Skip to content

Http

persista.http

Contain HTTP utilities.

persista.http.httpx

Contain httpx utilities.

persista.http.httpx.AsyncHttpClient

A wrapper around :class:httpx.AsyncClient with automatic retries and optional response caching.

This is the async counterpart of :class:HttpClient. See its docstring for the retry and caching behavior; the only difference is that the wrapped client is an :class:httpx.AsyncClient and caching is done through :class:~persista.cache.cache.Cache's async methods (aget/aset).

Parameters:

Name Type Description Default
timeout int

Default request timeout in seconds per attempt.

30
max_retries int

Default maximum number of retry attempts on transient failures.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry by default.

DEFAULT_RETRY_STATUS_CODES
cache Cache | None

An optional :class:~persista.cache.cache.Cache used to cache responses. None (the default) disables caching entirely.

None
cacheable_methods set[str] | frozenset[str]

The HTTP methods (case-insensitive) whose responses are cached, when cache is given. Defaults to {"GET"}.

frozenset({'GET'})
client AsyncClient

The :class:httpx.AsyncClient to wrap. The caller owns its lifecycle (creation and closing).

required
Example
>>> import asyncio
>>> import httpx
>>> from persista.http.httpx import AsyncHttpClient
>>> async def main():  # doctest: +SKIP
...     async with httpx.AsyncClient() as httpx_client:
...         client = AsyncHttpClient(client=httpx_client)
...         response = await client.get("https://jsonplaceholder.typicode.com/todos/1")
...
>>> asyncio.run(main())  # doctest: +SKIP

persista.http.httpx.AsyncHttpClient.delete async

delete(url: str, **kwargs: Any) -> Response

Send a DELETE request.

See :meth:request.

persista.http.httpx.AsyncHttpClient.get async

get(url: str, **kwargs: Any) -> Response

Send a GET request.

See :meth:request.

persista.http.httpx.AsyncHttpClient.patch async

patch(url: str, **kwargs: Any) -> Response

Send a PATCH request.

See :meth:request.

persista.http.httpx.AsyncHttpClient.post async

post(url: str, **kwargs: Any) -> Response

Send a POST request.

See :meth:request.

persista.http.httpx.AsyncHttpClient.put async

put(url: str, **kwargs: Any) -> Response

Send a PUT request.

See :meth:request.

persista.http.httpx.AsyncHttpClient.request async

request(
    method: str,
    url: str,
    *,
    timeout: int | None = None,
    max_retries: int | None = None,
    retry_status_codes: (
        set[int] | frozenset[int] | None
    ) = None,
    **kwargs: Any
) -> Response

Send an HTTP request, serving/storing it via the cache when enabled for method.

See :meth:HttpClient.request.

persista.http.httpx.HttpClient

A wrapper around :class:httpx.Client with automatic retries and optional response caching.

Retry behavior is delegated to :func:~persista.http.httpx.send_request. Caching is opt-in: it is only performed when cache is given, and only for methods listed in cacheable_methods. Cached entries store the response's status code, headers, and content, so a cache hit reconstructs an :class:httpx.Response equivalent to the one that was cached. Only successful (2xx) responses are cached.

Parameters:

Name Type Description Default
timeout int

Default request timeout in seconds per attempt.

30
max_retries int

Default maximum number of retry attempts on transient failures.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry by default.

DEFAULT_RETRY_STATUS_CODES
cache Cache | None

An optional :class:~persista.cache.cache.Cache used to cache responses. None (the default) disables caching entirely.

None
cacheable_methods set[str] | frozenset[str]

The HTTP methods (case-insensitive) whose responses are cached, when cache is given. Defaults to {"GET"}.

frozenset({'GET'})
client Client

The :class:httpx.Client to wrap. The caller owns its lifecycle (creation and closing).

required
Example
>>> import httpx
>>> from persista.http.httpx import HttpClient
>>> with httpx.Client() as httpx_client:  # doctest: +SKIP
...     client = HttpClient(client=httpx_client)
...     response = client.get("https://jsonplaceholder.typicode.com/todos/1")
...

persista.http.httpx.HttpClient.delete

delete(url: str, **kwargs: Any) -> Response

Send a DELETE request.

See :meth:request.

persista.http.httpx.HttpClient.get

get(url: str, **kwargs: Any) -> Response

Send a GET request.

See :meth:request.

persista.http.httpx.HttpClient.patch

patch(url: str, **kwargs: Any) -> Response

Send a PATCH request.

See :meth:request.

persista.http.httpx.HttpClient.post

post(url: str, **kwargs: Any) -> Response

Send a POST request.

See :meth:request.

persista.http.httpx.HttpClient.put

put(url: str, **kwargs: Any) -> Response

Send a PUT request.

See :meth:request.

persista.http.httpx.HttpClient.request

request(
    method: str,
    url: str,
    *,
    timeout: int | None = None,
    max_retries: int | None = None,
    retry_status_codes: (
        set[int] | frozenset[int] | None
    ) = None,
    **kwargs: Any
) -> Response

Send an HTTP request, serving/storing it via the cache when enabled for method.

Parameters:

Name Type Description Default
method str

The HTTP method to use, e.g. "GET".

required
url str

The full URL to send the request to.

required
timeout int | None

Per-call timeout override. Defaults to the value given at construction.

None
max_retries int | None

Per-call max-retries override. Defaults to the value given at construction.

None
retry_status_codes set[int] | frozenset[int] | None

Per-call retry-status-codes override. Defaults to the value given at construction.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.Client.request, e.g. headers, json, params.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed

Response

request, from the cache if it was a hit.

persista.http.httpx.delete_response

delete_response(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: Client | None = None,
    **kwargs: Any
) -> Response

Send a DELETE request with automatic retries and timeout.

This is a convenience wrapper around :func:send_request for the common case of issuing a DELETE request. See :func:send_request for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client Client | None

An optional :class:httpx.Client to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.Client.request, e.g. headers, params.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> from persista.http.httpx import delete_response
>>> response = delete_response(  # doctest: +SKIP
...     "https://jsonplaceholder.typicode.com/todos/1",
...     timeout=10,
...     max_retries=5,
... )

persista.http.httpx.delete_response_async async

delete_response_async(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: AsyncClient | None = None,
    **kwargs: Any
) -> Response

Send a DELETE request asynchronously with automatic retries and timeout.

This is a convenience wrapper around :func:send_request_async for the common case of issuing a DELETE request. See :func:send_request_async for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client AsyncClient | None

An optional :class:httpx.AsyncClient to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.AsyncClient.request, e.g. headers, params.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> import asyncio
>>> from persista.http.httpx import delete_response_async
>>> response = asyncio.run(  # doctest: +SKIP
...     delete_response_async(
...         "https://jsonplaceholder.typicode.com/todos/1",
...         timeout=10,
...         max_retries=5,
...     )
... )

persista.http.httpx.get_response

get_response(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: Client | None = None,
    **kwargs: Any
) -> Response

Fetch a URL with automatic retries and timeout.

This is a convenience wrapper around :func:send_request for the common case of issuing a GET request. See :func:send_request for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to fetch.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client Client | None

An optional :class:httpx.Client to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.Client.request, e.g. headers, params.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> from persista.http.httpx import get_response
>>> response = get_response(  # doctest: +SKIP
...     "https://jsonplaceholder.typicode.com/todos/1",
...     timeout=10,
...     max_retries=5,
... )

persista.http.httpx.get_response_async async

get_response_async(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: AsyncClient | None = None,
    **kwargs: Any
) -> Response

Fetch a URL asynchronously with automatic retries and timeout.

This is a convenience wrapper around :func:send_request_async for the common case of issuing a GET request. See :func:send_request_async for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to fetch.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client AsyncClient | None

An optional :class:httpx.AsyncClient to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.AsyncClient.request, e.g. headers, params.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> import asyncio
>>> from persista.http.httpx import get_response_async
>>> response = asyncio.run(  # doctest: +SKIP
...     get_response_async(
...         "https://jsonplaceholder.typicode.com/todos/1",
...         timeout=10,
...         max_retries=5,
...     )
... )

persista.http.httpx.patch_response

patch_response(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: Client | None = None,
    **kwargs: Any
) -> Response

Send a PATCH request with automatic retries and timeout.

This is a convenience wrapper around :func:send_request for the common case of issuing a PATCH request. See :func:send_request for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client Client | None

An optional :class:httpx.Client to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.Client.request, e.g. headers, json, data, params, content, files.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> from persista.http.httpx import patch_response
>>> response = patch_response(  # doctest: +SKIP
...     "https://jsonplaceholder.typicode.com/todos/1",
...     json={"title": "example"},
...     timeout=10,
...     max_retries=5,
... )

persista.http.httpx.patch_response_async async

patch_response_async(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: AsyncClient | None = None,
    **kwargs: Any
) -> Response

Send a PATCH request asynchronously with automatic retries and timeout.

This is a convenience wrapper around :func:send_request_async for the common case of issuing a PATCH request. See :func:send_request_async for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client AsyncClient | None

An optional :class:httpx.AsyncClient to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.AsyncClient.request, e.g. headers, json, data, params, content, files.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> import asyncio
>>> from persista.http.httpx import patch_response_async
>>> response = asyncio.run(  # doctest: +SKIP
...     patch_response_async(
...         "https://jsonplaceholder.typicode.com/todos/1",
...         json={"title": "example"},
...         timeout=10,
...         max_retries=5,
...     )
... )

persista.http.httpx.post_response

post_response(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: Client | None = None,
    **kwargs: Any
) -> Response

Send a POST request with automatic retries and timeout.

This is a convenience wrapper around :func:send_request for the common case of issuing a POST request. See :func:send_request for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client Client | None

An optional :class:httpx.Client to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.Client.request, e.g. headers, json, data, params, content, files.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> from persista.http.httpx import post_response
>>> response = post_response(  # doctest: +SKIP
...     "https://jsonplaceholder.typicode.com/todos",
...     json={"title": "example"},
...     timeout=10,
...     max_retries=5,
... )

persista.http.httpx.post_response_async async

post_response_async(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: AsyncClient | None = None,
    **kwargs: Any
) -> Response

Send a POST request asynchronously with automatic retries and timeout.

This is a convenience wrapper around :func:send_request_async for the common case of issuing a POST request. See :func:send_request_async for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client AsyncClient | None

An optional :class:httpx.AsyncClient to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.AsyncClient.request, e.g. headers, json, data, params, content, files.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> import asyncio
>>> from persista.http.httpx import post_response_async
>>> response = asyncio.run(  # doctest: +SKIP
...     post_response_async(
...         "https://jsonplaceholder.typicode.com/todos",
...         json={"title": "example"},
...         timeout=10,
...         max_retries=5,
...     )
... )

persista.http.httpx.put_response

put_response(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: Client | None = None,
    **kwargs: Any
) -> Response

Send a PUT request with automatic retries and timeout.

This is a convenience wrapper around :func:send_request for the common case of issuing a PUT request. See :func:send_request for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client Client | None

An optional :class:httpx.Client to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.Client.request, e.g. headers, json, data, params, content, files.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> from persista.http.httpx import put_response
>>> response = put_response(  # doctest: +SKIP
...     "https://jsonplaceholder.typicode.com/todos/1",
...     json={"title": "example"},
...     timeout=10,
...     max_retries=5,
... )

persista.http.httpx.put_response_async async

put_response_async(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: AsyncClient | None = None,
    **kwargs: Any
) -> Response

Send a PUT request asynchronously with automatic retries and timeout.

This is a convenience wrapper around :func:send_request_async for the common case of issuing a PUT request. See :func:send_request_async for full documentation of the retry and backoff behavior.

Parameters:

Name Type Description Default
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client AsyncClient | None

An optional :class:httpx.AsyncClient to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.AsyncClient.request, e.g. headers, json, data, params, content, files.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> import asyncio
>>> from persista.http.httpx import put_response_async
>>> response = asyncio.run(  # doctest: +SKIP
...     put_response_async(
...         "https://jsonplaceholder.typicode.com/todos/1",
...         json={"title": "example"},
...         timeout=10,
...         max_retries=5,
...     )
... )

persista.http.httpx.send_request

send_request(
    method: str,
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: Client | None = None,
    **kwargs: Any
) -> Response

Send an HTTP request with automatic retries and timeout.

Uses exponential backoff to handle transient network failures, connection timeouts, and 5xx server errors. Successive retry delays are 1s, 2s, 4s, and so on up to max_retries attempts.

If a client is provided it is used directly, allowing callers to share a single client across multiple calls for connection pooling. Otherwise a new client is created and closed automatically.

Parameters:

Name Type Description Default
method str

The HTTP method to use, e.g. "GET", "POST", "PUT", "PATCH", "DELETE".

required
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client Client | None

An optional :class:httpx.Client to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.Client.request, e.g. headers, json, data, params, content, files.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> from persista.http.httpx import send_request
>>> response = send_request(  # doctest: +SKIP
...     "POST",
...     "https://jsonplaceholder.typicode.com/todos",
...     json={"title": "example"},
...     timeout=10,
...     max_retries=5,
... )

persista.http.httpx.send_request_async async

send_request_async(
    method: str,
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: (
        set[int] | frozenset[int]
    ) = DEFAULT_RETRY_STATUS_CODES,
    client: AsyncClient | None = None,
    **kwargs: Any
) -> Response

Send an HTTP request asynchronously with automatic retries and timeout.

Uses exponential backoff to handle transient network failures, connection timeouts, and 5xx server errors. Successive retry delays are 1s, 2s, 4s, and so on up to max_retries attempts.

If a client is provided it is used directly, allowing callers to share a single client across multiple calls for connection pooling. Otherwise a new client is created and closed automatically.

Parameters:

Name Type Description Default
method str

The HTTP method to use, e.g. "GET", "POST", "PUT", "PATCH", "DELETE".

required
url str

The full URL to send the request to.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30. Ignored when client is provided.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries.

3
retry_status_codes set[int] | frozenset[int]

The HTTP status codes that trigger a retry. Defaults to {429, 500, 502, 503, 504}.

DEFAULT_RETRY_STATUS_CODES
client AsyncClient | None

An optional :class:httpx.AsyncClient to reuse. When None, a new client is created and closed after the request completes.

None
**kwargs Any

Additional keyword arguments forwarded to :meth:httpx.AsyncClient.request, e.g. headers, json, data, params, content, files.

{}

Returns:

Name Type Description
The Response

class:httpx.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the httpx package is not installed.

HTTPStatusError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

TransportError

If the host is unreachable or the request times out after all retries are exhausted.

Example
>>> import asyncio
>>> from persista.http.httpx import send_request_async
>>> response = asyncio.run(  # doctest: +SKIP
...     send_request_async(
...         "POST",
...         "https://jsonplaceholder.typicode.com/todos",
...         json={"title": "example"},
...         timeout=10,
...         max_retries=5,
...     )
... )

persista.http.requests

Provide HTTP helper functions for fetching remote content.

persista.http.requests.create_session

create_session(
    max_retries: int = 3,
    retry_status_codes: list[int] | None = None,
    backoff_factor: float = 1,
) -> Session

Create a :class:requests.Session with a retry adapter mounted.

Configures exponential backoff retries for transient failures on both https:// and http:// connections. Useful for sharing a single session across multiple requests for connection pooling.

Parameters:

Name Type Description Default
max_retries int

Maximum number of retry attempts on transient failures with exponential backoff. Defaults to 3.

3
retry_status_codes list[int] | None

HTTP status codes that should trigger a retry. Pass None to use the default set (429, 500, 502, 503, 504).

None
backoff_factor float

Multiplier used to compute the delay between retry attempts. Successive delays are backoff_factor * (2 ** (retry_number - 1)) seconds. Defaults to 1.

1

Returns:

Type Description
Session

A configured :class:requests.Session with retry adapters mounted

Session

on both https:// and http://.

Example
>>> from persista.http.requests import create_session
>>> session = create_session(max_retries=5)

persista.http.requests.fetch_response

fetch_response(
    url: str,
    *,
    timeout: int = 30,
    max_retries: int = 3,
    retry_status_codes: list[int] | None = None,
    backoff_factor: float = 1,
    headers: dict[str, str] | None = None,
    session: Session | None = None
) -> Response

Fetch a URL with automatic retries and timeout.

Uses exponential backoff to handle transient network failures, connection timeouts, and 5xx server errors. Successive retry delays are backoff_factor * 1s, 2s, 4s, and so on up to max_retries attempts.

If a session is provided it is used directly, allowing callers to share a single session across multiple calls for connection pooling. Otherwise a new session is created and closed automatically.

Parameters:

Name Type Description Default
url str

The full URL to fetch.

required
timeout int

Request timeout in seconds per attempt. Defaults to 30.

30
max_retries int

Maximum number of retry attempts on transient failures. Defaults to 3. Set to 0 to disable retries. Ignored when session is provided.

3
retry_status_codes list[int] | None

HTTP status codes that should trigger a retry. Pass None to use the default set (429, 500, 502, 503, 504). Ignored when session is provided.

None
backoff_factor float

Multiplier used to compute the delay between retry attempts. Defaults to 1. Ignored when session is provided.

1
headers dict[str, str] | None

HTTP headers to include in the request. Pass None to send no custom headers (the default). Pass an empty dict to send no headers explicitly.

None
session Session | None

An optional :class:requests.Session to reuse. When None, a new session is created via :func:create_session and closed after the request completes.

None

Returns:

Name Type Description
The Response

class:requests.Response object for the completed request.

Raises:

Type Description
RuntimeError

if the requests package is not installed.

ConnectTimeout

If all retry attempts exceed timeout seconds.

HTTPError

On 4xx/5xx responses that are not retried (e.g. 404, 403).

ConnectionError

If the host is unreachable after all retries are exhausted.

RequestException

For any other unrecoverable network failure.

Example
>>> from persista.http.requests import fetch_response
>>> html = fetch_response(  # doctest: +SKIP
...     "https://jsonplaceholder.typicode.com/todos/1",
...     timeout=10,
...     max_retries=5,
... )