philiprehberger-http-retry
Resilient HTTP client with automatic retries and configurable backoff.
Installation
pip install philiprehberger-http-retry
Usage
from philiprehberger_http_retry import (
resilient_get,
resilient_post,
resilient_put,
resilient_patch,
resilient_delete,
resilient_head,
Session,
)
Simple Requests
# GET request with default retries (3 attempts, exponential backoff)
response = resilient_get("https://api.example.com/data")
print(response.read().decode())
# POST with JSON body
response = resilient_post(
"https://api.example.com/items",
json_data={"name": "widget", "count": 5},
)
# PUT with JSON body
response = resilient_put(
"https://api.example.com/items/42",
json_data={"name": "widget", "count": 7},
)
# PATCH with JSON body
response = resilient_patch(
"https://api.example.com/items/42",
json_data={"status": "active"},
)
# DELETE request
response = resilient_delete("https://api.example.com/items/42")
# HEAD request (e.g. existence/size check)
response = resilient_head("https://api.example.com/items/42")
Backoff Strategies
from philiprehberger_http_retry import resilient_request
# Exponential backoff (default): 0.5s, 1s, 2s, ...
resilient_request("GET", url, backoff="exponential")
# Linear backoff: 0.5s, 1s, 1.5s, ...
resilient_request("GET", url, backoff="linear")
# Constant backoff: 0.5s, 0.5s, 0.5s, ...
resilient_request("GET", url, backoff="constant")
# Custom callable: receives attempt number, returns delay in seconds
resilient_request("GET", url, backoff=lambda attempt: 0.1 * (attempt + 1))
Retry Hook
import logging
def log_retry(attempt: int, error: Exception) -> None:
logging.warning(f"Retry {attempt}: {error}")
response = resilient_get(
"https://api.example.com/data",
on_retry=log_retry,
)
Circuit breaker
from philiprehberger_http_retry import (
CircuitBreaker,
CircuitBreakerOpen,
resilient_get,
)
breaker = CircuitBreaker(failure_threshold=5, reset_timeout=30.0)
try:
response = resilient_get(
"https://flaky-api.example.com/data",
circuit_breaker=breaker,
)
except CircuitBreakerOpen as err:
print(f"Breaker tripped, retry after unix time {err.next_retry_at:.0f}")
The breaker counts request outcomes (not retry attempts). After
failure_threshold consecutive failures it trips to open and rejects
calls until reset_timeout elapses, then probes one request in
half_open before returning to closed.
Session with Defaults
session = Session(
base_url="https://api.example.com",
default_headers={"Authorization": "Bearer token123"},
retries=5,
backoff="linear",
timeout=15,
on_retry=log_retry,
)
response = session.get("/users")
response = session.post("/users", json_data={"name": "Alice"})
Error Handling
from philiprehberger_http_retry import resilient_get, RetryExhaustedError
try:
response = resilient_get("https://unreliable-api.example.com/data")
except RetryExhaustedError as err:
print(f"Failed after {err.attempts} attempts: {err.last_error}")
API
| Function / Class | Description |
|---|---|
resilient_request(method, url, **kwargs) |
Core retry function. Supports data, headers, retries, backoff, timeout, retry_on, on_retry. |
resilient_get(url, **kwargs) |
GET convenience wrapper around resilient_request. |
resilient_post(url, data=None, json_data=None, **kwargs) |
POST wrapper. Auto-serializes json_data and sets Content-Type. |
resilient_put(url, data=None, json_data=None, **kwargs) |
PUT wrapper. Auto-serializes json_data and sets Content-Type. |
resilient_patch(url, data=None, json_data=None, **kwargs) |
PATCH wrapper. Auto-serializes json_data and sets Content-Type. |
resilient_delete(url, **kwargs) |
DELETE convenience wrapper around resilient_request. |
resilient_head(url, **kwargs) |
HEAD convenience wrapper around resilient_request. |
Session(base_url, default_headers, retries, backoff, timeout, retry_on, on_retry, circuit_breaker) |
Stores defaults. Methods: get(path), post(path). |
CircuitBreaker(failure_threshold, reset_timeout, half_open_max_calls) |
Trips to open after consecutive failures, probes via half_open. Methods: allow_request(), record_success(), record_failure(). |
CircuitBreakerOpen |
Raised when the breaker rejects a request. Attribute: .next_retry_at (unix timestamp). |
RetryExhaustedError |
Raised after all retries fail. Attributes: .attempts, .last_error. |
Development
pip install -e .
python -m pytest tests/ -v
Support
If you find this project useful:
License
Metadata
Release files for philiprehberger-http-retry 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| philiprehberger_http_retry-0.5.0.tar.gz | 188.4 kB | Without provenance | Details for philiprehberger_http_retry-0.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| philiprehberger_http_retry-0.5.0-py3-none-any.whl | Python 3 | none | any | Details for philiprehberger_http_retry-0.5.0-py3-none-any.whl |
Total release size: 196.4 kB
Release files / philiprehberger_http_retry-0.5.0.tar.gz
| Download URL | philiprehberger_http_retry-0.5.0.tar.gz |
|---|---|
| Size | 188.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
88c6a99831ef37aa01cd9b141fe959a4424e7212ba68cac45a858e2c4bde59c0
|
|
BLAKE2b-256 checksum How to use checksums |
6bde60f863b27a363e88dac22305298f9d9eea55a4749bf35a4a7860f40f17fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Release files / philiprehberger_http_retry-0.5.0-py3-none-any.whl
| Download URL | philiprehberger_http_retry-0.5.0-py3-none-any.whl |
|---|---|
| Size | 8.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bcae1c1308a4fd04758e8c5b1d1154bbba99aa7f296024eec0459602bd9f739c
|
|
BLAKE2b-256 checksum How to use checksums |
f7a924f29e88d039a7a00b9896979e19af229d01ebe1540f35a72257adeb4e60
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.13
|
Security for philiprehberger-http-retry 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.