You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+26-3Lines changed: 26 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,9 +7,9 @@
7
7
8
8
**Async HTTP client framework for Python.**
9
9
10
-
`httpware` is a thin opinionated wrapper around `httpx2`. It re-exports `httpx2.Request`/`httpx2.Response`, adds a middleware chain composed at client construction, supports opt-in typed response decoding (pydantic and msgspec are both extras), and raises a status-keyed exception tree automatically on 4xx/5xx.
10
+
`httpware` is a thin opinionated wrapper around `httpx2`. It re-exports `httpx2.Request`/`httpx2.Response`, adds a middleware chain composed at client construction, supports opt-in typed response decoding (pydantic and msgspec are both extras), and raises a status-keyed exception tree automatically on 4xx/5xx. It also ships a small resilience suite — `Retry` middleware with a Finagle-style `RetryBudget`, plus a `Bulkhead` concurrency limiter — under `httpware.middleware.resilience`.
11
11
12
-
> **Status:** Pre-1.0 (0.3.0). Public API is subject to change between minor releases until v1.0. Resilience middleware (retry / timeout / bulkhead), streaming, and observability are not yet shipped.
12
+
> **Status:** Pre-1.0. Public API is subject to change between minor releases until v1.0. Streaming and observability are not yet shipped.
Copy file name to clipboardExpand all lines: docs/index.md
+28-3Lines changed: 28 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,8 +1,8 @@
1
1
# httpware
2
2
3
-
A Python async HTTP client framework for building resilient service clients. `httpware`owns the abstraction layer above the underlying HTTP client (`httpx2` by default); consumers never import the transport directly.
3
+
A Python async HTTP client framework for building resilient service clients. `httpware`is a thin opinionated wrapper around `httpx2` — it re-exports `httpx2.Request`/`httpx2.Response` as the public request/response surface, adds a middleware chain (with a built-in resilience suite: `Retry` + `RetryBudget`, `Bulkhead`), opt-in typed response decoding, and a status-keyed exception tree raised automatically on 4xx/5xx.
4
4
5
-
> **Status:** Pre-1.0 (0.1.0 alpha). Public API is subject to change between minor releases until v1.0.
5
+
> **Status:** Pre-1.0. Public API is subject to change between minor releases until v1.0. Streaming and observability are not yet shipped.
6
6
7
7
## Install
8
8
@@ -13,6 +13,7 @@ pip install httpware
13
13
Optional extras:
14
14
15
15
```bash
16
+
pip install httpware[pydantic] # PydanticDecoder (the default decoder path)
16
17
pip install httpware[msgspec] # MsgspecDecoder
17
18
```
18
19
@@ -39,10 +40,34 @@ async def main() -> None:
39
40
asyncio.run(main())
40
41
```
41
42
43
+
### With resilience middleware
44
+
45
+
Compose resilience middleware at construction; `Bulkhead` goes outside `Retry` so one slot covers all retry attempts.
46
+
47
+
```python
48
+
from httpware import AsyncClient, Bulkhead, Retry
49
+
50
+
51
+
asyncdefmain() -> None:
52
+
asyncwith AsyncClient(
53
+
base_url="https://api.example.com",
54
+
middleware=[
55
+
Bulkhead(max_concurrent=10), # cap total in-flight
user =await client.get("/users/1", response_model=User)
60
+
```
61
+
62
+
## Errors
63
+
64
+
All 4xx/5xx responses raise typed exceptions automatically: `NotFoundError`, `ServiceUnavailableError`, `RateLimitedError`, etc. — all subclasses of `httpware.StatusError`. Transport-layer transient failures raise `NetworkError`; the resilience middleware raise `RetryBudgetExhaustedError` and `BulkheadFullError`. Everything inherits `httpware.ClientError`.
65
+
42
66
## Where to go next
43
67
44
-
-**[Engineering Notes](dev/engineering.md)** — design invariants, the five protocol seams, exception contract, module layout, testing patterns, optional-extras pattern.
68
+
-**[Engineering Notes](https://github.com/modern-python/httpware/blob/main/planning/engineering.md)** — design invariants, the three protocol seams, exception contract, module layout, testing patterns, optional-extras pattern. Lives in the repo at `planning/engineering.md`.
Copy file name to clipboardExpand all lines: planning/engineering.md
+9-3Lines changed: 9 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ This doc is the single distilled reference for `httpware` design rationale, prot
4
4
5
5
## 1. Project intent
6
6
7
-
`httpware` is a thin opinionated wrapper around `httpx2`. It re-exports `httpx2.Request` and `httpx2.Response` as the public request/response surface and adds three things on top: typed response decoding (via a `ResponseDecoder` protocol; pydantic and msgspec are both opt-in extras as of 0.3.0), a middleware chain composed at client construction, and a status-keyed exception tree raised automatically on 4xx and 5xx. `AsyncClient(decoder=None)` defaults to constructing a `PydanticDecoder` and so requires the `pydantic` extra; callers can supply an explicit `decoder=` argument to escape the default.
7
+
`httpware` is a thin opinionated wrapper around `httpx2`. It re-exports `httpx2.Request` and `httpx2.Response` as the public request/response surface and adds three things on top: typed response decoding (via a `ResponseDecoder` protocol; pydantic and msgspec are both opt-in extras as of 0.3.0), a middleware chain composed at client construction, and a status-keyed exception tree raised automatically on 4xx and 5xx. `AsyncClient(decoder=None)` defaults to constructing a `PydanticDecoder` and so requires the `pydantic` extra; callers can supply an explicit `decoder=` argument to escape the default. As of 0.4.0, the package ships a small resilience suite under `httpware.middleware.resilience` — a `Retry` middleware with a Finagle-style `RetryBudget`, plus a `Bulkhead` concurrency limiter — composed via the standard middleware chain.
8
8
9
9
The 0.1.0 release attempted to own a full abstraction over the underlying HTTP client. v0.2 walks that back: `httpx2` is part of the public surface.
10
10
@@ -70,10 +70,16 @@ src/httpware/
70
70
├── __init__.py # public exports
71
71
├── py.typed
72
72
├── client.py # AsyncClient
73
-
├── errors.py # status-keyed exception tree (response: httpx2.Response)
0 commit comments