0
# Request Handling
1
2
Request object providing access to HTTP request data including headers, query parameters, form data, file uploads, cookies, and JSON data.
3
4
## Capabilities
5
6
### Request Object
7
8
The global request object provides access to all HTTP request data for the current request.
9
10
```python { .api }
11
request: LocalRequest
12
"""Global thread-local request instance available in route handlers."""
13
```
14
15
### Request Properties
16
17
Access HTTP request metadata and content.
18
19
```python { .api }
20
class BaseRequest:
21
@property
22
def method(self) -> str:
23
"""HTTP method (GET, POST, PUT, DELETE, etc.)."""
24
25
@property
26
def path(self) -> str:
27
"""Request path without query string."""
28
29
@property
30
def fullpath(self) -> str:
31
"""Request path with query string."""
32
33
@property
34
def url(self) -> str:
35
"""Full request URL."""
36
37
@property
38
def urlparts(self) -> SplitResult:
39
"""Parsed URL components."""
40
41
@property
42
def environ(self) -> dict:
43
"""WSGI environ dictionary."""
44
45
@property
46
def route(self) -> Route:
47
"""The Route object that matched this request."""
48
```
49
50
### Query Parameters
51
52
Access URL query string parameters.
53
54
```python { .api }
55
class BaseRequest:
56
@property
57
def query(self) -> FormsDict:
58
"""Query string parameters as FormsDict."""
59
60
@property
61
def query_string(self) -> str:
62
"""Raw query string."""
63
```
64
65
Usage:
66
67
```python
68
# URL: /search?q=python&page=2
69
@route('/search')
70
def search():
71
query = request.query.q # 'python'
72
page = request.query.get('page', 1, type=int) # 2
73
return f'Searching for: {query}, page: {page}'
74
```
75
76
### Form Data
77
78
Access form data from POST requests.
79
80
```python { .api }
81
class BaseRequest:
82
@property
83
def forms(self) -> FormsDict:
84
"""Form data from POST request body."""
85
86
@property
87
def params(self) -> FormsDict:
88
"""Combined query parameters and form data."""
89
```
90
91
Usage:
92
93
```python
94
@route('/login', method='POST')
95
def login():
96
username = request.forms.get('username')
97
password = request.forms.get('password')
98
return f'Login attempt: {username}'
99
```
100
101
### File Uploads
102
103
Handle file uploads in multipart forms.
104
105
```python { .api }
106
class BaseRequest:
107
@property
108
def files(self) -> FormsDict:
109
"""Uploaded files as FileUpload objects."""
110
111
class FileUpload:
112
@property
113
def name(self) -> str:
114
"""Form field name."""
115
116
@property
117
def filename(self) -> str:
118
"""Original filename."""
119
120
@property
121
def file(self):
122
"""File-like object for reading."""
123
124
@property
125
def headers(self) -> HeaderDict:
126
"""Upload headers."""
127
128
def save(self, destination, overwrite=False, chunk_size=65536):
129
"""
130
Save uploaded file to destination.
131
132
Parameters:
133
- destination: str, file path or file-like object
134
- overwrite: bool, whether to overwrite existing files
135
- chunk_size: int, read chunk size in bytes
136
"""
137
```
138
139
Usage:
140
141
```python
142
@route('/upload', method='POST')
143
def upload():
144
upload = request.files.get('file')
145
if upload:
146
upload.save('/uploads/' + upload.filename)
147
return f'Uploaded: {upload.filename}'
148
return 'No file uploaded'
149
```
150
151
### JSON Data
152
153
Access JSON request body data.
154
155
```python { .api }
156
class BaseRequest:
157
@property
158
def json(self) -> Any:
159
"""
160
Parsed JSON request body.
161
162
Returns:
163
Any: parsed JSON data or None if not JSON or parse error
164
"""
165
```
166
167
Usage:
168
169
```python
170
@route('/api/data', method='POST')
171
def api_data():
172
data = request.json
173
if data:
174
return {'received': data}
175
return {'error': 'No JSON data'}
176
```
177
178
### Headers
179
180
Access HTTP request headers.
181
182
```python { .api }
183
class BaseRequest:
184
@property
185
def headers(self) -> HeaderDict:
186
"""Request headers as case-insensitive dictionary."""
187
188
def get_header(self, name, default=None):
189
"""
190
Get request header value.
191
192
Parameters:
193
- name: str, header name (case-insensitive)
194
- default: any, default value if header not found
195
196
Returns:
197
str or default: header value
198
"""
199
```
200
201
Usage:
202
203
```python
204
@route('/api/test')
205
def test():
206
auth = request.get_header('Authorization')
207
content_type = request.headers.get('Content-Type')
208
user_agent = request.get_header('User-Agent', 'Unknown')
209
return {'auth': auth, 'content_type': content_type, 'user_agent': user_agent}
210
```
211
212
### Cookies
213
214
Access request cookies.
215
216
```python { .api }
217
class BaseRequest:
218
@property
219
def cookies(self) -> SimpleCookie:
220
"""Request cookies as SimpleCookie object."""
221
222
def get_cookie(self, key, default=None, secret=None, digestmod=hashlib.sha256):
223
"""
224
Get cookie value, optionally validating signed cookies.
225
226
Parameters:
227
- key: str, cookie name
228
- default: any, default value if cookie not found
229
- secret: str, secret for signed cookie validation
230
- digestmod: hashlib algorithm for signature verification
231
232
Returns:
233
str or default: cookie value
234
"""
235
```
236
237
Usage:
238
239
```python
240
@route('/profile')
241
def profile():
242
user_id = request.get_cookie('user_id')
243
session = request.get_cookie('session', secret='my-secret')
244
if user_id and session:
245
return f'User: {user_id}'
246
return 'Not logged in'
247
```
248
249
### Content and Body
250
251
Access raw request body and content information.
252
253
```python { .api }
254
class BaseRequest:
255
@property
256
def body(self) -> bytes:
257
"""Raw request body as bytes."""
258
259
@property
260
def content_length(self) -> int:
261
"""Content-Length header value."""
262
263
@property
264
def content_type(self) -> str:
265
"""Content-Type header value."""
266
267
@property
268
def is_xhr(self) -> bool:
269
"""True if request is XMLHttpRequest (AJAX)."""
270
271
@property
272
def is_ajax(self) -> bool:
273
"""Alias for is_xhr."""
274
```
275
276
### Request Context
277
278
Additional request context and utilities.
279
280
```python { .api }
281
class BaseRequest:
282
@property
283
def script_name(self) -> str:
284
"""SCRIPT_NAME from WSGI environ."""
285
286
@property
287
def path_info(self) -> str:
288
"""PATH_INFO from WSGI environ."""
289
290
@property
291
def auth(self) -> tuple:
292
"""HTTP Basic Auth (username, password) or None."""
293
294
def get(self, value, default=None):
295
"""
296
Get value from WSGI environ.
297
298
Parameters:
299
- value: str, WSGI environ key
300
- default: any, default value
301
302
Returns:
303
any: environ value or default
304
"""
305
```
306
307
## Data Container Classes
308
309
### FormsDict
310
311
Dictionary for form data with multiple values per key and type conversion.
312
313
```python { .api }
314
class FormsDict(MultiDict):
315
def get(self, key, default=None, index=-1, type=None):
316
"""
317
Get form value with optional type conversion.
318
319
Parameters:
320
- key: str, form field name
321
- default: any, default value if not found
322
- index: int, value index for multi-value fields (-1 for last)
323
- type: callable, type conversion function
324
325
Returns:
326
any: form value, converted if type specified
327
"""
328
329
def getall(self, key):
330
"""Get all values for a form field as list."""
331
332
def getunicode(self, name, default=None, encoding=None):
333
"""
334
Get form value as unicode string.
335
336
Parameters:
337
- name: str, form field name
338
- default: any, default value
339
- encoding: str, character encoding
340
341
Returns:
342
str: unicode form value
343
"""
344
```
345
346
### MultiDict
347
348
Base dictionary class allowing multiple values per key.
349
350
```python { .api }
351
class MultiDict:
352
def get(self, key, default=None, index=-1, type=None):
353
"""Get value with optional type conversion."""
354
355
def getall(self, key):
356
"""Get all values for key as list."""
357
358
def append(self, key, value):
359
"""Append value to key."""
360
361
def replace(self, key, value):
362
"""Replace all values for key with single value."""
363
364
def getlist(self, key):
365
"""Alias for getall."""
366
```
367
368
### HeaderDict
369
370
Case-insensitive dictionary for HTTP headers.
371
372
```python { .api }
373
class HeaderDict(MultiDict):
374
"""Case-insensitive MultiDict for HTTP headers."""
375
376
def get(self, key, default=None, index=-1):
377
"""Get header value (case-insensitive key)."""
378
379
def getall(self, key):
380
"""Get all header values (case-insensitive key)."""
381
```