FastAPI-style WebSocket framework with built-in docs and testing
Project description
SocketSpec
FastAPI-style WebSocket framework with built-in interactive docs and testing.
Install
pip install socketspec[fastapi]
Quickstart
from fastapi import FastAPI
from pydantic import BaseModel
from socketspec import SocketApp
from socketspec.adapters.fastapi import mount
socket = SocketApp(docs=True)
class ChatMessage(BaseModel):
room: str
text: str
class MessageAck(BaseModel):
status: str
message_id: str
@socket.on(
"send_message",
description="Send a chat message to a room.",
tags=["chat"],
emits=[Emits("message_ack", model=MessageAck, description="Delivery confirmation")],
broadcasts=[Broadcasts("new_message", room="chat:{room}", description="Delivered to room members")],
)
async def send_message(conn, payload: ChatMessage) -> None:
await conn.emit("message_ack", {"status": "ok", "message_id": "abc123"})
await socket.rooms.broadcast(
"chat:" + payload.room,
"new_message",
{"from": conn.id, "text": payload.text},
)
app = FastAPI()
mount(socket, app, path="/ws")
uvicorn main:app --reload
Docs UI
Open /socket-docs in your browser after starting the server.
- Click an event card to expand its schema
- Hit Try it out to send a live WebSocket message
- See the server response appear inline, without leaving the browser
- Open a second tab and connect as a different user to test broadcasts
Why SocketSpec
| Feature | python-socketio | channels (Django) | SocketSpec |
|---|---|---|---|
| FastAPI-native | ✗ | ✗ | ✅ |
| Pydantic payload validation | ✗ | ✗ | ✅ |
| Built-in interactive docs | ✗ | ✗ | ✅ |
TestClient for unit tests |
✗ | partial | ✅ |
| Room guards / permissions | manual | manual | ✅ |
Dependency injection (Depends) |
✗ | ✗ | ✅ |
Type-safe (mypy --strict) |
✗ | ✗ | ✅ |
Core Concepts
Event handlers look exactly like FastAPI route handlers:
@socket.on("join_room", tags=["rooms"])
async def join_room(conn: Connection, payload: JoinPayload) -> None:
await socket.rooms.join(conn, f"chat:{payload.room_id}")
Rooms with pattern-based guards:
@socket.room_guard("admin:{room}")
async def admin_only(conn: Connection, room: str) -> bool:
return conn.identity.role == "admin"
Testing without a real server:
from socketspec.testing import TestClient
async def test_send_message():
async with TestClient(socket) as client:
conn = await client.connect()
await conn.send("send_message", {"room": "general", "text": "hello"})
response = await conn.receive()
assert response["event"] == "message_ack"
Links
License
Apache 2.0 — see LICENSE. Created and maintained by Laiba Shahab.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file socketspec-0.1.0.tar.gz.
File metadata
- Download URL: socketspec-0.1.0.tar.gz
- Upload date:
- Size: 17.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02b12ff9b8c2f2ac154222ed5fe0c6daebddcba9e2d8bc8bd278fc0158f39ab7
|
|
| MD5 |
8a82cd0966e2ebb2d1518438a915b7a7
|
|
| BLAKE2b-256 |
271db9bd54aa0c96e5056ecbf07daa8a2cdcf1b7a8aec5789c3c0b303d8ad65b
|
File details
Details for the file socketspec-0.1.0-py3-none-any.whl.
File metadata
- Download URL: socketspec-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
960de9b0deeea855626a5866bd104975b7026a5b0130f51073b4ea6c59fb2209
|
|
| MD5 |
f9c761b9de2b90bd2a49eff50dfefa00
|
|
| BLAKE2b-256 |
dbb71c699efca2d57a61e9aec35caee0e188e5e82f8ba8512d08269a01f07634
|