Path params work like REST
FastAPI's path parameters work identically for WebSocket endpoints. @app.websocket('/ws/{room_id}') gives you a room_id: str argument. Type-hint it for automatic conversion: room_id: int, user_id: UUID, etc.
Query params via websocket.query_params
Custom HTTP headers are not settable from the browser WebSocket constructor (Track 2). So query strings carry the auth token, room name, and other handshake data. Read them via websocket.query_params — a dict-like mapping of strings.
Validate before accept()
Always validate auth and reject before accept(). Closing during the handshake costs nothing; closing after accept means the client briefly sees an "open" socket and then a kick — confusing UX and easier to mishandle on the client.