|
| 1 | +# httpware 0.2.0 — thin httpx2 wrapper |
| 2 | + |
| 3 | +**0.2.0 is a breaking rewrite.** The framework is now a thin opinionated wrapper around `httpx2`: it re-exports `httpx2.Request`/`httpx2.Response`, adds a middleware chain, typed response decoding, and a status-keyed exception tree raised automatically on 4xx/5xx. |
| 4 | + |
| 5 | +## Breaking changes from 0.1.0 |
| 6 | + |
| 7 | +- **Removed value types.** `httpware.Request`, `httpware.Response`, `httpware.StreamResponse`, `httpware.Limits`, `httpware.Timeout`, and `httpware.ClientConfig` are gone. Use `httpx2.Request`, `httpx2.Response`, `httpx2.Limits`, `httpx2.Timeout` directly. |
| 8 | +- **Removed transport abstraction.** `httpware.Transport`, `httpware.Httpx2Transport`, and `httpware.RecordedTransport` are gone. Tests should inject `httpx2.MockTransport` via the new `httpx2_client=` kwarg. |
| 9 | +- **Removed auth coercion.** Pass `httpx2.Auth` (e.g., `httpx2.BasicAuth`) directly to the client. |
| 10 | +- **`with_options` removed.** Construct a separate `AsyncClient` wrapping a shared `httpx2.AsyncClient` instead. |
| 11 | +- **`StatusError` simplified.** Subclasses no longer accept `status` / `body` / `headers` / `json` / `request_method` / `request_url` kwargs. Construct with a single `response: httpx2.Response` argument and read fields from `exc.response.*`. |
| 12 | +- **CI invariant retired.** The "no `httpx2` imports outside `transports/httpx2.py`" rule is gone. `httpx2` is part of the public surface. |
| 13 | + |
| 14 | +## What still works |
| 15 | + |
| 16 | +- `AsyncClient.get/post/put/patch/delete/head/options/request` with `response_model=...` for typed decoding. |
| 17 | +- `PydanticDecoder` (default) and `MsgspecDecoder` (opt-in via `pip install httpware[msgspec]`). |
| 18 | +- Middleware protocol with `@before_request`, `@after_response`, `@on_error` decorators. |
| 19 | +- Status-keyed exception tree (`NotFoundError`, `RateLimitedError`, etc.) raised automatically on 4xx/5xx. |
| 20 | + |
| 21 | +## Migration |
| 22 | + |
| 23 | +```python |
| 24 | +# Before (0.1.0) |
| 25 | +import httpware |
| 26 | + |
| 27 | +async with httpware.AsyncClient(base_url="https://api.example.com", auth="my-token") as client: |
| 28 | + user = await client.get("/users/1", response_model=User) |
| 29 | +``` |
| 30 | + |
| 31 | +```python |
| 32 | +# After (0.2.0) |
| 33 | +import httpx2 |
| 34 | +import httpware |
| 35 | + |
| 36 | +async with httpware.AsyncClient( |
| 37 | + base_url="https://api.example.com", |
| 38 | + headers={"Authorization": "Bearer my-token"}, |
| 39 | +) as client: |
| 40 | + user = await client.get("/users/1", response_model=User) |
| 41 | +``` |
| 42 | + |
| 43 | +## What's next |
| 44 | + |
| 45 | +Epic 3 (resilience middleware — retry, timeout, bulkhead) and Epic 5 (observability) ship in subsequent minor releases. See `planning/engineering.md` section 8 for the post-pivot roadmap. |
0 commit comments