Add native WebSocket support by vendoring httpx-ws
Merged
KL
3mo ago+3243+3243+0123456789012345678901234567890123456789-7-7-0123456789
Ports httpx-ws (MIT, by @frankie567) into httpx2 as a native httpx2.websockets package, preserving the full upstream commit history via a subtree-style merge.
What you get
httpx2.websocket("ws://…"),Client().websocket(…),AsyncClient().websocket(…)WebSocketSession/AsyncWebSocketSession,ASGIWebSocketTransportfor testing WebSocket endpoints against ASGI apps, and the exception hierarchy (HTTPXWSException,WebSocketDisconnect,WebSocketUpgradeError, …), all exported fromhttpx2.websockets
import httpx2
from httpx2.websockets import WebSocketDisconnect
with httpx2.websocket("ws://localhost:8000/ws") as ws:
ws.send_text("Hello!")
message = ws.receive_text()
Design
wsprotois an optional extrahttpx2[ws], matching thebrotli/http2/sockspattern. WebSocket features raise a clear "installhttpx2[ws]" error when it is missing.httpx2.websocketsis a public subpackage, so the types live there rather than being re-exported at the top level. Because users import it explicitly,httpx2/__init__.pynever imports it, andimport httpx2pulls in neither the subpackage norwsproto- no lazy__getattr__machinery needed to keep the extra optional. The top-level namespace grows by exactly one line (thewebsocketexport); everything inside the package is private (_api,_exceptions,_ping,_transport).- The
.websocket()methods mirror the existing.sse()shape and lazily import inside the method body, so they cost nothing at import time. - WebSocket defaults live in
_config.pyalongsideDEFAULT_TIMEOUT_CONFIGand friends. httpcore2stays lazily imported inside the methods that need it, preserving httpx2's existing lazy-loading.- The vendored code is adapted to httpx2's namespaces and typing standards (passes
ruffandmypy --strict).
History
The vendor commit merges httpx-ws's complete history (98 commits) under the WebSocket package, so upstream authorship and provenance are preserved.
Tests
Vendored httpx-ws tests live under tests/httpx2/websockets/ (136 passing across asyncio and trio), including a test that import httpx2 does not import wsproto. Dev deps added: starlette, websockets, flaky. scripts/check is green and coverage stays at 100%.
AI Disclaimer
This PR was developed with the assistance of either Claude or Codex. I've reviewed and verified the changes.