pondsocket-asgi
Canonical ASGI adapter for pondsocket. Mount under any ASGI host — FastAPI, Starlette, Litestar, Django, raw uvicorn.
Handles WebSocket and SSE (Server-Sent Events) transports. The same PondSocket instance serves both — the adapter detects the request type and dispatches.
Install
pip install pondsocket-asgi
Pulls in pondsocket and pondsocket-common automatically.
Quick start: raw uvicorn
from pondsocket import ConnectionContext, EventContext, JoinContext, PondSocket
from pondsocket_asgi import PondASGIApp
async def auth(ctx: ConnectionContext) -> None:
ctx.accept()
async def on_join(ctx: JoinContext) -> None:
await ctx.accept()
async def on_message(ctx: EventContext) -> None:
await ctx.broadcast(ctx.event_name, ctx.get_payload())
pond = PondSocket()
endpoint = pond.create_endpoint("/socket", auth)
lobby = endpoint.create_channel("/chat/:room_id", on_join)
lobby.on_message("message", on_message)
app = PondASGIApp(pond)
uvicorn module:app --host 127.0.0.1 --port 8000
WebSocket clients connect to ws://127.0.0.1:8000/socket.
Mount under FastAPI
from fastapi import FastAPI
from pondsocket_asgi import PondASGIApp
app = FastAPI()
app.mount("/ws", PondASGIApp(pond))
When mounted at /ws, the adapter sees scope["path"] already stripped of the prefix — register your pond endpoints with the post-mount path (e.g. /socket resolves at ws://host/ws/socket).
See examples/ for FastAPI, Starlette, and raw uvicorn variants.
SSE transport
The same endpoint serves Server-Sent Events to clients that don't have WebSocket:
GET /socket
Accept: text/event-stream
→ 200, response carries X-Connection-ID header and a `CONNECTION` event with `payload.connectionId`, stream of "event: <name>\ndata: <json>\n\n" frames
POST /socket
X-Connection-ID: <id>
Content-Type: application/json
body: <client message JSON>
→ 204
DELETE /socket
X-Connection-ID: <id>
→ 204
Use SSE when WebSocket is blocked (some corporate proxies). The connection handler is the same — the adapter routes by Accept header and method.
Lifespan
PondASGIApp handles the ASGI lifespan protocol. On lifespan.startup, it acknowledges immediately. On lifespan.shutdown, it closes the PondSocket (which closes every endpoint, every channel, every transport).
Testing
pondsocket_asgi.testing exposes an in-memory ASGI driver — no real network needed:
from pondsocket_asgi.testing import ASGITestDriver
driver = ASGITestDriver(PondASGIApp(pond))
# WebSocket
session = await driver.connect_websocket("/socket")
await session.send_client_message(
action="JOIN_CHANNEL",
channel_name="/chat/1",
event="join",
)
ack = await session.receive_json()
await session.disconnect()
# SSE
sse = await driver.connect_sse("/socket")
status, _ = await driver.sse_push(sse.connection_id, {"action": "BROADCAST", ...})
frame = await sse.receive_event()
await sse.disconnect()
# Lifespan
lifespan = await driver.open_lifespan()
await lifespan.startup()
await lifespan.shutdown()
Public API
from pondsocket_asgi import ...
PondASGIApp— the adapter itselfASGIWebSocketTransport— WebSocket transport (you usually don't construct this directly; the app does)
from pondsocket_asgi.testing import ...
ASGITestDriver,WebSocketSession,LifespanSession,SSESession
License
GPL-3.0-or-later.
Metadata
Release files for pondsocket-asgi 0.0.6
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 |
|---|---|---|---|---|
| pondsocket_asgi-0.0.6.tar.gz | 12.6 kB | Without provenance | Details for pondsocket_asgi-0.0.6.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pondsocket_asgi-0.0.6-py3-none-any.whl | Python 3 | none | any | Details for pondsocket_asgi-0.0.6-py3-none-any.whl |
Total release size: 24.0 kB
Release files / pondsocket_asgi-0.0.6.tar.gz
| Download URL | pondsocket_asgi-0.0.6.tar.gz |
|---|---|
| Size | 12.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9c41ffdcf8d6a5d9607b9da98a400dd7819ecfc0294c41330f2031a5fd4cce07
|
|
BLAKE2b-256 checksum How to use checksums |
7a9b7a1b008e877744466d34833107eccde5083ce0645c57bb2c97642afa9784
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|
Release files / pondsocket_asgi-0.0.6-py3-none-any.whl
| Download URL | pondsocket_asgi-0.0.6-py3-none-any.whl |
|---|---|
| Size | 11.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
30d4a4ef4782cb3234e4dd87b0c28598a86648684da3bb7c20c3ed471d2bcd21
|
|
BLAKE2b-256 checksum How to use checksums |
4c496da1e40def628336df2f513683641f48f1f385217b676b10699679d5a6ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.0
|
Security for pondsocket-asgi 0.0.6
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.