Гайды

WebSockets: чат на FastAPI

Минимальный эндпоинт, комната в памяти, аутентификация, JSON-протокол, heartbeat и мульти-инстанс.

~10 мин чтения

WebSockets: чат на FastAPI

WebSocket — полнодуплексный канал поверх HTTP с upgrade; сервер и клиент шлют фреймы без оверхеда нового HTTP-запроса на каждое сообщение. В FastAPI — WebSocket из Starlette. База фреймворка — Быстрый старт с FastAPI; asyncio — asyncio в Python; прокси — Деплой FastAPI: Docker и Nginx.


1. Минимальный эндпоинт

python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect

app = FastAPI()

@app.websocket("/ws")
async def ws_endpoint(ws: WebSocket):
    await ws.accept()
    try:
        while True:
            data = await ws.receive_text()
            await ws.send_text(f"echo: {data}")
    except WebSocketDisconnect:
        pass

2. Чат-комната (память процесса)

python
class Room:
    def __init__(self):
        self.clients: set[WebSocket] = set()

    async def connect(self, ws: WebSocket):
        await ws.accept()
        self.clients.add(ws)

    def disconnect(self, ws: WebSocket):
        self.clients.discard(ws)

    async def broadcast(self, message: str):
        for c in list(self.clients):
            await c.send_text(message)

rooms: dict[str, Room] = {}

@app.websocket("/chat/{room_id}")
async def chat(ws: WebSocket, room_id: str):
    room = rooms.setdefault(room_id, Room())
    await room.connect(ws)
    try:
        while True:
            msg = await ws.receive_text()
            await room.broadcast(msg)
    except WebSocketDisconnect:
        room.disconnect(ws)

Для нескольких инстансов приложения нужен pub/subRedis Pub/Sub и очереди, NATS.


3. Аутентификация

  • Токен в query: wss://api/ws?token=... (осторожно с логами).
  • Или cookie + same-site политика.
  • После accept() можно отклонить, отправив close и вернув из хендлера.

4. Протокол сообщений

Используйте JSON с полем type (join, message, error) для совместимости клиентов.


5. Heartbeat

Прокси и балансировщики рвут «тихие» соединения. Периодически шлите ping (Starlette умеет автоматический ping/pong WebSocket) или прикладной keep-alive.


6. Масштаб и backpressure

Не накапливайте неограниченную очередь исходящих сообщений; при перегрузке — close с кодом.


7. Чек-лист

  • wss:// в проде.
  • Nginx proxy_read_timeout достаточен.
  • Мульти-инстанс — общий брокер для broadcast.
  • Валидация входящих JSON (размер, схема).

Дальше: WebRTC · тег FastAPI