pypi-fastapi

Description
FastAPI framework, high performance, easy to learn, fast to code, ready for production
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/pypi-fastapi@0.116.0

websocket-support.md docs/

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