0
# WebSocket Support
1
2
FastAPI provides comprehensive WebSocket support for real-time bidirectional communication between clients and servers. This enables applications to push data to clients instantly and receive real-time updates from clients.
3
4
## Capabilities
5
6
### WebSocket Connection Class
7
8
The WebSocket class handles real-time bidirectional communication with clients, providing methods for sending and receiving data in various formats.
9
10
```python { .api }
11
class WebSocket:
12
def __init__(self, scope: Scope, receive: Receive, send: Send) -> None:
13
"""
14
Initialize WebSocket connection.
15
16
Parameters:
17
- scope: ASGI scope dictionary
18
- receive: ASGI receive callable
19
- send: ASGI send callable
20
"""
21
22
async def accept(
23
self,
24
subprotocol: str = None,
25
headers: List[Tuple[bytes, bytes]] = None
26
) -> None:
27
"""
28
Accept the WebSocket connection.
29
30
Parameters:
31
- subprotocol: WebSocket subprotocol to use
32
- headers: Additional headers to send
33
"""
34
35
async def receive_text(self) -> str:
36
"""
37
Receive text data from the WebSocket.
38
39
Returns:
40
String containing the received text message
41
"""
42
43
async def receive_bytes(self) -> bytes:
44
"""
45
Receive binary data from the WebSocket.
46
47
Returns:
48
Bytes containing the received binary message
49
"""
50
51
async def receive_json(self, mode: str = "text") -> Any:
52
"""
53
Receive JSON data from the WebSocket.
54
55
Parameters:
56
- mode: Receive mode ("text" or "binary")
57
58
Returns:
59
Parsed JSON data as Python object
60
"""
61
62
async def send_text(self, data: str) -> None:
63
"""
64
Send text data to the WebSocket.
65
66
Parameters:
67
- data: Text message to send
68
"""
69
70
async def send_bytes(self, data: bytes) -> None:
71
"""
72
Send binary data to the WebSocket.
73
74
Parameters:
75
- data: Binary message to send
76
"""
77
78
async def send_json(self, data: Any, mode: str = "text") -> None:
79
"""
80
Send JSON data to the WebSocket.
81
82
Parameters:
83
- data: Python object to serialize and send as JSON
84
- mode: Send mode ("text" or "binary")
85
"""
86
87
async def close(self, code: int = 1000, reason: str = None) -> None:
88
"""
89
Close the WebSocket connection.
90
91
Parameters:
92
- code: WebSocket close code
93
- reason: Close reason string
94
"""
95
96
@property
97
def client(self) -> Address:
98
"""Client address information."""
99
100
@property
101
def url(self) -> URL:
102
"""WebSocket URL information."""
103
104
@property
105
def headers(self) -> Headers:
106
"""WebSocket headers."""
107
108
@property
109
def query_params(self) -> QueryParams:
110
"""WebSocket query parameters."""
111
112
@property
113
def path_params(self) -> dict:
114
"""WebSocket path parameters."""
115
116
@property
117
def cookies(self) -> dict:
118
"""WebSocket cookies."""
119
120
@property
121
def state(self) -> State:
122
"""WebSocket connection state."""
123
```
124
125
### WebSocket State Enumeration
126
127
Enumeration defining the possible states of a WebSocket connection.
128
129
```python { .api }
130
class WebSocketState(enum.Enum):
131
"""WebSocket connection state constants."""
132
133
CONNECTING = 0
134
CONNECTED = 1
135
DISCONNECTED = 3
136
```
137
138
### WebSocket Disconnect Exception
139
140
Exception raised when a WebSocket connection is unexpectedly disconnected.
141
142
```python { .api }
143
class WebSocketDisconnect(Exception):
144
def __init__(self, code: int = 1000, reason: str = None) -> None:
145
"""
146
WebSocket disconnect exception.
147
148
Parameters:
149
- code: WebSocket close code
150
- reason: Disconnect reason
151
"""
152
self.code = code
153
self.reason = reason
154
```
155
156
### WebSocket Route Decorator
157
158
Decorator method on FastAPI and APIRouter instances for defining WebSocket endpoints.
159
160
```python { .api }
161
def websocket(
162
self,
163
path: str,
164
*,
165
name: str = None,
166
dependencies: List[Depends] = None,
167
) -> Callable[[DecoratedCallable], DecoratedCallable]:
168
"""
169
Decorator for WebSocket endpoints.
170
171
Parameters:
172
- path: WebSocket URL path
173
- name: Endpoint name for URL generation
174
- dependencies: List of dependencies for this WebSocket
175
"""
176
```
177
178
### WebSocket Route Class
179
180
Class representing individual WebSocket routes in the application.
181
182
```python { .api }
183
class APIWebSocketRoute:
184
def __init__(
185
self,
186
path: str,
187
endpoint: Callable,
188
*,
189
name: str = None,
190
dependencies: List[Depends] = None,
191
) -> None:
192
"""
193
WebSocket route representation.
194
195
Parameters:
196
- path: WebSocket URL path
197
- endpoint: WebSocket handler function
198
- name: Route name for URL generation
199
- dependencies: List of dependencies for the WebSocket
200
"""
201
202
def matches(self, scope: Scope) -> Tuple[Match, Scope]:
203
"""Check if route matches the given scope."""
204
205
def url_path_for(self, name: str, **path_params: Any) -> URLPath:
206
"""Generate URL path for the named route."""
207
```
208
209
## Usage Examples
210
211
### Basic WebSocket Endpoint
212
213
```python
214
from fastapi import FastAPI, WebSocket
215
216
app = FastAPI()
217
218
@app.websocket("/ws")
219
async def websocket_endpoint(websocket: WebSocket):
220
await websocket.accept()
221
try:
222
while True:
223
data = await websocket.receive_text()
224
await websocket.send_text(f"Message text was: {data}")
225
except WebSocketDisconnect:
226
print("Client disconnected")
227
```
228
229
### WebSocket with Path Parameters
230
231
```python
232
from fastapi import FastAPI, WebSocket
233
234
app = FastAPI()
235
236
@app.websocket("/ws/{client_id}")
237
async def websocket_endpoint(websocket: WebSocket, client_id: int):
238
await websocket.accept()
239
try:
240
while True:
241
data = await websocket.receive_text()
242
await websocket.send_text(f"Client {client_id}: {data}")
243
except WebSocketDisconnect:
244
print(f"Client {client_id} disconnected")
245
```
246
247
### WebSocket with Dependencies
248
249
```python
250
from fastapi import FastAPI, WebSocket, Depends, HTTPException
251
from fastapi.security import HTTPBearer
252
253
app = FastAPI()
254
security = HTTPBearer()
255
256
def verify_websocket_token(token: str = Depends(security)):
257
if token.credentials != "valid-token":
258
raise HTTPException(status_code=401, detail="Invalid token")
259
return token.credentials
260
261
@app.websocket("/ws")
262
async def websocket_endpoint(
263
websocket: WebSocket,
264
token: str = Depends(verify_websocket_token)
265
):
266
await websocket.accept()
267
await websocket.send_text(f"Authenticated with token: {token}")
268
try:
269
while True:
270
data = await websocket.receive_text()
271
await websocket.send_text(f"Echo: {data}")
272
except WebSocketDisconnect:
273
print("Authenticated client disconnected")
274
```
275
276
### WebSocket JSON Communication
277
278
```python
279
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
280
from typing import Dict, Any
281
282
app = FastAPI()
283
284
@app.websocket("/ws/json")
285
async def websocket_json_endpoint(websocket: WebSocket):
286
await websocket.accept()
287
try:
288
while True:
289
# Receive JSON data
290
data: Dict[str, Any] = await websocket.receive_json()
291
292
# Process the data
293
response = {
294
"type": "response",
295
"original_message": data,
296
"timestamp": "2023-01-01T00:00:00Z"
297
}
298
299
# Send JSON response
300
await websocket.send_json(response)
301
except WebSocketDisconnect:
302
print("JSON WebSocket client disconnected")
303
```
304
305
### WebSocket Connection Manager
306
307
```python
308
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
309
from typing import List
310
311
class ConnectionManager:
312
def __init__(self):
313
self.active_connections: List[WebSocket] = []
314
315
async def connect(self, websocket: WebSocket):
316
await websocket.accept()
317
self.active_connections.append(websocket)
318
319
def disconnect(self, websocket: WebSocket):
320
self.active_connections.remove(websocket)
321
322
async def send_personal_message(self, message: str, websocket: WebSocket):
323
await websocket.send_text(message)
324
325
async def broadcast(self, message: str):
326
for connection in self.active_connections:
327
await connection.send_text(message)
328
329
app = FastAPI()
330
manager = ConnectionManager()
331
332
@app.websocket("/ws/{client_id}")
333
async def websocket_endpoint(websocket: WebSocket, client_id: int):
334
await manager.connect(websocket)
335
try:
336
while True:
337
data = await websocket.receive_text()
338
await manager.send_personal_message(f"You wrote: {data}", websocket)
339
await manager.broadcast(f"Client #{client_id} says: {data}")
340
except WebSocketDisconnect:
341
manager.disconnect(websocket)
342
await manager.broadcast(f"Client #{client_id} left the chat")
343
```
344
345
### WebSocket with Query Parameters
346
347
```python
348
from fastapi import FastAPI, WebSocket, Query
349
350
app = FastAPI()
351
352
@app.websocket("/ws")
353
async def websocket_endpoint(
354
websocket: WebSocket,
355
room: str = Query(..., description="Chat room name"),
356
user_id: int = Query(..., description="User ID")
357
):
358
await websocket.accept()
359
await websocket.send_text(f"Welcome to room {room}, user {user_id}!")
360
361
try:
362
while True:
363
message = await websocket.receive_text()
364
await websocket.send_text(f"[{room}] User {user_id}: {message}")
365
except WebSocketDisconnect:
366
print(f"User {user_id} left room {room}")
367
```
368
369
### WebSocket Error Handling
370
371
```python
372
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
373
import json
374
375
app = FastAPI()
376
377
@app.websocket("/ws/safe")
378
async def safe_websocket_endpoint(websocket: WebSocket):
379
await websocket.accept()
380
381
try:
382
while True:
383
try:
384
# Receive and validate JSON
385
data = await websocket.receive_text()
386
parsed_data = json.loads(data)
387
388
if "action" not in parsed_data:
389
await websocket.send_json({
390
"error": "Missing 'action' field"
391
})
392
continue
393
394
# Process valid messages
395
response = {
396
"success": True,
397
"action": parsed_data["action"],
398
"data": parsed_data.get("data")
399
}
400
await websocket.send_json(response)
401
402
except json.JSONDecodeError:
403
await websocket.send_json({
404
"error": "Invalid JSON format"
405
})
406
except Exception as e:
407
await websocket.send_json({
408
"error": f"Processing error: {str(e)}"
409
})
410
411
except WebSocketDisconnect:
412
print("Client disconnected from safe WebSocket")
413
```
414
415
### WebSocket with Custom Close Handling
416
417
```python
418
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
419
420
app = FastAPI()
421
422
@app.websocket("/ws/custom-close")
423
async def websocket_with_custom_close(websocket: WebSocket):
424
await websocket.accept()
425
426
try:
427
while True:
428
data = await websocket.receive_text()
429
430
if data == "close":
431
await websocket.close(code=1000, reason="Client requested close")
432
break
433
elif data == "error":
434
await websocket.close(code=1011, reason="Server error occurred")
435
break
436
else:
437
await websocket.send_text(f"Received: {data}")
438
439
except WebSocketDisconnect as disconnect:
440
print(f"WebSocket disconnected with code: {disconnect.code}, reason: {disconnect.reason}")
441
```