0
# Request and Response
1
2
HTTP request and response handling with comprehensive support for headers, query parameters, form data, file uploads, and various response types including HTML, file serving, and streaming responses.
3
4
## Capabilities
5
6
### Request Object
7
8
The Request object contains all information about an incoming HTTP request.
9
10
```python { .api }
11
@dataclass
12
class Request:
13
query_params: QueryParams
14
headers: Headers
15
path_params: dict[str, str]
16
body: Union[str, bytes]
17
method: str
18
url: Url
19
form_data: dict[str, str]
20
files: dict[str, bytes]
21
ip_addr: Optional[str]
22
identity: Optional[Identity]
23
24
def json(self) -> dict:
25
"""
26
Parse request body as JSON.
27
28
Returns:
29
dict: Parsed JSON data
30
31
Raises:
32
ValueError: If body is not valid JSON
33
"""
34
```
35
36
### Response Object
37
38
The Response object represents an HTTP response with status, headers, and body.
39
40
```python { .api }
41
@dataclass
42
class Response:
43
status_code: int
44
headers: Union[Headers, dict]
45
description: Union[str, bytes]
46
response_type: Optional[str]
47
file_path: Optional[str]
48
49
def set_cookie(self, key: str, value: str):
50
"""
51
Set a cookie in the response.
52
53
Args:
54
key: Cookie name
55
value: Cookie value
56
"""
57
```
58
59
### Headers Management
60
61
Handle HTTP headers with get, set, and contains operations.
62
63
```python { .api }
64
class Headers:
65
def __init__(self, default_headers: Optional[dict] = None):
66
"""
67
Initialize headers container.
68
69
Args:
70
default_headers: Optional default headers dictionary
71
"""
72
73
def get(self, key: str) -> Optional[str]:
74
"""
75
Get header value by key.
76
77
Args:
78
key: Header name (case-insensitive)
79
80
Returns:
81
Header value or None if not found
82
"""
83
84
def set(self, key: str, value: str):
85
"""
86
Set header value.
87
88
Args:
89
key: Header name
90
value: Header value
91
"""
92
93
def append(self, key: str, value: str):
94
"""
95
Append value to existing header.
96
97
Args:
98
key: Header name
99
value: Value to append
100
"""
101
102
def contains(self, key: str) -> bool:
103
"""
104
Check if header exists.
105
106
Args:
107
key: Header name
108
109
Returns:
110
True if header exists, False otherwise
111
"""
112
113
def populate_from_dict(self, headers: dict[str, str]):
114
"""
115
Populate headers from dictionary.
116
117
Args:
118
headers: Dictionary of header name-value pairs
119
"""
120
121
def is_empty(self) -> bool:
122
"""
123
Check if headers container is empty.
124
125
Returns:
126
True if no headers are set
127
"""
128
```
129
130
### Query Parameters
131
132
Handle URL query parameters with support for multiple values per key.
133
134
```python { .api }
135
class QueryParams:
136
def get(self, key: str, default: Optional[str] = None) -> Optional[str]:
137
"""
138
Get first value for a query parameter.
139
140
Args:
141
key: Parameter name
142
default: Default value if parameter not found
143
144
Returns:
145
Parameter value or default
146
"""
147
148
def get_first(self, key: str) -> Optional[str]:
149
"""
150
Get first value for a parameter.
151
152
Args:
153
key: Parameter name
154
155
Returns:
156
First value or None
157
"""
158
159
def get_all(self, key: str) -> list[str]:
160
"""
161
Get all values for a parameter.
162
163
Args:
164
key: Parameter name
165
166
Returns:
167
List of all values for the parameter
168
"""
169
170
def set(self, key: str, value: str):
171
"""
172
Set parameter value (replaces existing).
173
174
Args:
175
key: Parameter name
176
value: Parameter value
177
"""
178
179
def contains(self, key: str) -> bool:
180
"""
181
Check if parameter exists.
182
183
Args:
184
key: Parameter name
185
186
Returns:
187
True if parameter exists
188
"""
189
190
def empty(self) -> bool:
191
"""
192
Check if query parameters are empty.
193
194
Returns:
195
True if no parameters are set
196
"""
197
198
def extend(self, other: QueryParams):
199
"""
200
Extend with parameters from another QueryParams object.
201
202
Args:
203
other: Another QueryParams instance
204
"""
205
206
def to_dict(self) -> dict:
207
"""
208
Convert to dictionary representation.
209
210
Returns:
211
Dictionary of parameter name-value pairs
212
"""
213
```
214
215
### Response Utilities
216
217
Various utilities for creating different types of HTTP responses.
218
219
```python { .api }
220
def html(html_content: str) -> Response:
221
"""
222
Create an HTML response.
223
224
Args:
225
html_content: HTML content string
226
227
Returns:
228
Response with HTML content-type
229
"""
230
231
def serve_file(file_path: str, file_name: Optional[str] = None) -> "FileResponse":
232
"""
233
Serve a file for download.
234
235
Args:
236
file_path: Path to file to serve
237
file_name: Optional custom filename for download
238
239
Returns:
240
FileResponse for file download
241
"""
242
243
def serve_html(file_path: str) -> "FileResponse":
244
"""
245
Serve an HTML file.
246
247
Args:
248
file_path: Path to HTML file
249
250
Returns:
251
FileResponse with HTML content-type
252
"""
253
254
class FileResponse:
255
def __init__(
256
self,
257
file_path: str,
258
status_code: Optional[int] = None,
259
headers: Optional[Headers] = None,
260
):
261
"""
262
Response for serving files with automatic content-type detection.
263
264
Args:
265
file_path: Path to file to serve
266
status_code: HTTP status code (defaults to 200)
267
headers: Optional response headers
268
"""
269
```
270
271
### Streaming Responses
272
273
Support for streaming responses and Server-Sent Events (SSE).
274
275
```python { .api }
276
class StreamingResponse:
277
def __init__(
278
self,
279
content: Union[Generator, AsyncGenerator],
280
status_code: Optional[int] = None,
281
headers: Optional[Headers] = None,
282
media_type: str = "text/event-stream"
283
):
284
"""
285
Create a streaming response.
286
287
Args:
288
content: Generator or async generator yielding response chunks
289
status_code: HTTP status code
290
headers: Response headers
291
media_type: Content-Type header value
292
"""
293
294
def SSEResponse(
295
content: Union[Generator, AsyncGenerator],
296
status_code: Optional[int] = None,
297
headers: Optional[Headers] = None
298
) -> StreamingResponse:
299
"""
300
Create a Server-Sent Events response.
301
302
Args:
303
content: Generator yielding SSE messages
304
status_code: HTTP status code
305
headers: Response headers
306
307
Returns:
308
StreamingResponse configured for SSE
309
"""
310
311
def SSEMessage(
312
data: str,
313
event: Optional[str] = None,
314
id: Optional[str] = None,
315
retry: Optional[int] = None
316
) -> str:
317
"""
318
Format a Server-Sent Events message.
319
320
Args:
321
data: Message data
322
event: Event type
323
id: Message ID
324
retry: Retry timeout in milliseconds
325
326
Returns:
327
Formatted SSE message string
328
"""
329
```
330
331
### JSON Utilities
332
333
JSON serialization utilities using high-performance orjson library.
334
335
```python { .api }
336
def jsonify(input_dict: dict) -> str:
337
"""
338
Serialize dictionary to JSON string using orjson.
339
340
Args:
341
input_dict: Dictionary to serialize
342
343
Returns:
344
JSON string representation
345
"""
346
```
347
348
### HTTP Status Codes
349
350
Comprehensive HTTP status code constants.
351
352
```python { .api }
353
# All standard HTTP status codes available as constants
354
HTTP_200_OK = 200
355
HTTP_201_CREATED = 201
356
HTTP_204_NO_CONTENT = 204
357
HTTP_400_BAD_REQUEST = 400
358
HTTP_401_UNAUTHORIZED = 401
359
HTTP_403_FORBIDDEN = 403
360
HTTP_404_NOT_FOUND = 404
361
HTTP_405_METHOD_NOT_ALLOWED = 405
362
HTTP_500_INTERNAL_SERVER_ERROR = 500
363
# ... and many more status codes
364
```
365
366
## Usage Examples
367
368
### Handling Request Data
369
370
```python
371
from robyn import Robyn
372
373
app = Robyn(__file__)
374
375
@app.get("/user/<user_id>")
376
def get_user(request):
377
# Access path parameters
378
user_id = request.path_params["user_id"]
379
380
# Access query parameters
381
include_posts = request.query_params.get("include_posts", "false")
382
page = request.query_params.get("page", "1")
383
384
# Access headers
385
auth_header = request.headers.get("Authorization")
386
user_agent = request.headers.get("User-Agent")
387
388
return {
389
"user_id": user_id,
390
"include_posts": include_posts == "true",
391
"page": int(page),
392
"client_ip": request.ip_addr,
393
"user_agent": user_agent
394
}
395
396
@app.post("/users")
397
def create_user(request):
398
# Parse JSON body
399
user_data = request.json()
400
401
# Access form data (if form submission)
402
if request.form_data:
403
name = request.form_data.get("name")
404
email = request.form_data.get("email")
405
406
# Access uploaded files
407
if request.files:
408
avatar = request.files.get("avatar")
409
410
return {"message": "User created", "data": user_data}
411
412
app.start()
413
```
414
415
### Creating Custom Responses
416
417
```python
418
from robyn import Robyn, Response, Headers, status_codes, html, jsonify
419
420
app = Robyn(__file__)
421
422
@app.get("/custom")
423
def custom_response(request):
424
# Create custom response with headers
425
headers = Headers()
426
headers.set("X-Custom-Header", "MyValue")
427
headers.set("Cache-Control", "no-cache")
428
429
response = Response(
430
status_code=status_codes.HTTP_200_OK,
431
headers=headers,
432
description="Custom response content"
433
)
434
response.set_cookie("session_id", "abc123")
435
436
return response
437
438
@app.get("/json")
439
def json_response(request):
440
data = {"users": ["alice", "bob"], "count": 2}
441
return jsonify(data)
442
443
@app.get("/html")
444
def html_response(request):
445
return html("<h1>Hello, World!</h1><p>This is HTML content.</p>")
446
447
app.start()
448
```
449
450
### File Serving
451
452
```python
453
from robyn import Robyn, serve_file, serve_html
454
455
app = Robyn(__file__)
456
457
@app.get("/download/<filename>")
458
def download_file(request):
459
filename = request.path_params["filename"]
460
file_path = f"./uploads/{filename}"
461
return serve_file(file_path, filename)
462
463
@app.get("/report")
464
def view_report(request):
465
return serve_html("./reports/monthly_report.html")
466
467
app.start()
468
```
469
470
### Streaming Responses
471
472
```python
473
from robyn import Robyn, StreamingResponse, SSEResponse, SSEMessage
474
import time
475
import json
476
477
app = Robyn(__file__)
478
479
@app.get("/stream")
480
def stream_data(request):
481
def generate_data():
482
for i in range(10):
483
yield f"Data chunk {i}\n"
484
time.sleep(1)
485
486
return StreamingResponse(generate_data(), media_type="text/plain")
487
488
@app.get("/events")
489
def server_sent_events(request):
490
def generate_events():
491
for i in range(5):
492
data = json.dumps({"event": i, "timestamp": time.time()})
493
yield SSEMessage(data, event="update", id=str(i))
494
time.sleep(2)
495
496
return SSEResponse(generate_events())
497
498
app.start()
499
```
500
501
### Working with Headers and Query Parameters
502
503
```python
504
from robyn import Robyn, Headers
505
506
app = Robyn(__file__)
507
508
@app.get("/search")
509
def search(request):
510
# Handle multiple query parameters
511
query = request.query_params.get("q", "")
512
page = int(request.query_params.get("page", "1"))
513
filters = request.query_params.get_all("filter") # Get all filter values
514
515
# Check for specific headers
516
if request.headers.contains("Accept"):
517
accept_header = request.headers.get("Accept")
518
if "application/json" in accept_header:
519
return {"query": query, "page": page, "filters": filters}
520
521
# Return HTML response with custom headers
522
headers = Headers()
523
headers.set("Content-Type", "text/html")
524
headers.set("X-Search-Results", str(len(filters)))
525
526
html_content = f"<h1>Search Results</h1><p>Query: {query}</p>"
527
response = Response(200, headers, html_content)
528
529
return response
530
531
app.start()
532
```