Skip to content

modern-python/httpware

Repository files navigation

httpware

PyPI version Supported Python versions Downloads Coverage CI License GitHub stars Context7 uv Ruff ty

A Python HTTP client framework with sync and async clients for building resilient service clients.

Why httpware

  • Typed errors, no raise_for_status() — 4xx/5xx automatically raise a status-keyed exception tree (NotFoundError, RateLimitedError, …), all under httpware.StatusError.
  • Typed response bodiesresponse_model=YourType decodes the body straight to your pydantic or msgspec model; a missing decoder fails fast, before the request goes out.
  • Production resilience as composable middleware — retry + retry-budget, bulkhead, circuit breaker, and timeout, composed at construction — all over standard httpx2.

Built on httpx2: httpware re-exports httpx2.Request/httpx2.Response and stays a thin wrapper, not a new HTTP abstraction.

Status: Pre-1.0. Public API is subject to change between minor releases until v1.0.

Install

pip install httpware                # core only — no decoder
pip install httpware[pydantic]      # + PydanticDecoder — BaseModel, dataclasses, primitives, generics
pip install httpware[msgspec]       # + MsgspecDecoder — Struct, dataclasses, primitives, generics
pip install httpware[pydantic,msgspec]   # both — BaseModel routes to pydantic, Struct to msgspec
pip install httpware[all]           # everything (pydantic, msgspec, otel)

Quickstart

A typed GET against a live API (needs pip install httpware[pydantic]):

import asyncio

from httpware import AsyncClient
from pydantic import BaseModel


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


async def main() -> None:
    async with AsyncClient(base_url="https://jsonplaceholder.typicode.com") as client:
        user = await client.get("/users/1", response_model=User)
        print(user.name)  # Leanne Graham


asyncio.run(main())

The sync Client is identical — swap AsyncClientClient and drop the await / async with. A 4xx/5xx response raises a typed StatusError; a malformed body raises DecodeError. Both subclass httpware.ClientError.

Documentation

Full guides live at httpware.modern-python.org:

  • Quickstart & observability — resilience middleware, streaming, and the stable logger/event contract.
  • Middleware — write your own (auth, tracing, request-ID propagation).
  • Resilience — retry + retry-budget, bulkhead, circuit breaker, timeout.
  • Errors — the exception tree and catching strategies.
  • Testinghttpx2.MockTransport injection.
  • Recipes — DI wiring, phase-decorator patterns, link-header pagination.

🗒️ Release notes · 📦 PyPI · 📝 License

Part of modern-python

Browse the full list of templates and libraries in modern-python — see the org profile for the categorized index.

About

Resilience-first async HTTP client framework for Python

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Contributors