0
# Request Response Handling
1
2
Comprehensive system for processing HTTP requests and responses with automatic validation, serialization, and error handling based on OpenAPI specifications.
3
4
## Capabilities
5
6
### Request Context
7
8
Access to current request information through the context system.
9
10
```python { .api }
11
from connexion.context import request
12
13
# Request context properties
14
class RequestContext:
15
@property
16
def method(self) -> str:
17
"""HTTP method (GET, POST, etc.)"""
18
19
@property
20
def path(self) -> str:
21
"""Request path"""
22
23
@property
24
def query(self) -> dict:
25
"""Query parameters"""
26
27
@property
28
def headers(self) -> dict:
29
"""Request headers"""
30
31
@property
32
def body(self) -> bytes:
33
"""Raw request body"""
34
35
@property
36
def json(self) -> dict:
37
"""Parsed JSON body"""
38
39
@property
40
def form(self) -> dict:
41
"""Form data"""
42
43
@property
44
def files(self) -> dict:
45
"""Uploaded files"""
46
```
47
48
### ConnexionRequest
49
50
Enhanced request object with Connexion-specific functionality.
51
52
```python { .api }
53
class ConnexionRequest:
54
def __init__(self, *args, uri_parser=None, **kwargs):
55
"""
56
Initialize ConnexionRequest wrapping a Starlette request.
57
58
Parameters:
59
- *args: Arguments passed to Starlette Request
60
- uri_parser: URI parser instance
61
- **kwargs: Keyword arguments passed to Starlette Request
62
"""
63
64
@classmethod
65
def from_starlette_request(cls, request, uri_parser=None):
66
"""Create ConnexionRequest from existing Starlette request."""
67
68
async def get_body(self):
69
"""
70
Get processed request body based on content type.
71
72
Returns:
73
JSON dict for JSON content, form dict for form content, or None
74
"""
75
76
async def json(self):
77
"""
78
Parse request body as JSON.
79
80
Returns:
81
dict: Parsed JSON data or None if invalid
82
"""
83
84
@property
85
def content_type(self) -> str:
86
"""Content-Type header value"""
87
88
@property
89
def mimetype(self) -> str:
90
"""Media type without parameters"""
91
92
async def form(self) -> dict:
93
"""Form data from request body"""
94
95
async def files(self) -> dict:
96
"""Uploaded files from multipart request"""
97
98
@property
99
def query_params(self) -> dict:
100
"""URL query parameters"""
101
102
@property
103
def path_params(self) -> dict:
104
"""Path parameters from URL routing"""
105
106
@property
107
def context(self) -> dict:
108
"""Connexion request context"""
109
```
110
111
### ConnexionResponse
112
113
Response handling with automatic serialization and content negotiation.
114
115
```python { .api }
116
class ConnexionResponse:
117
def __init__(
118
self,
119
body=None,
120
status_code: int = 200,
121
headers: dict = None,
122
content_type: str = None
123
):
124
"""
125
Create a response object.
126
127
Parameters:
128
- body: Response body (dict, list, str, bytes, or None)
129
- status_code: HTTP status code
130
- headers: Response headers
131
- content_type: Content-Type header
132
"""
133
134
@property
135
def status_code(self) -> int:
136
"""HTTP status code"""
137
138
@property
139
def headers(self) -> dict:
140
"""Response headers"""
141
142
@property
143
def body(self):
144
"""Response body"""
145
146
@property
147
def content_type(self) -> str:
148
"""Content-Type header value"""
149
```
150
151
### Problem Response Handling
152
153
RFC 7807 Problem Details for HTTP APIs support.
154
155
```python { .api }
156
def problem(
157
status: int,
158
title: str,
159
detail: str = None,
160
type: str = None,
161
instance: str = None,
162
**kwargs
163
):
164
"""
165
Create an RFC 7807 problem response.
166
167
Parameters:
168
- status: HTTP status code
169
- title: Short, human-readable problem summary
170
- detail: Human-readable explanation specific to this occurrence
171
- type: URI that identifies the problem type
172
- instance: URI that identifies the specific occurrence
173
- **kwargs: Additional problem-specific properties
174
175
Returns:
176
Problem response dict with appropriate status code
177
"""
178
```
179
180
### NoContent Response
181
182
Special response type for empty responses.
183
184
```python { .api }
185
class NoContent:
186
"""
187
Represents an empty HTTP response body.
188
Used for 204 No Content and similar responses.
189
"""
190
pass
191
192
# Usage in endpoint functions
193
def delete_resource(resource_id: int):
194
# Delete the resource
195
return NoContent, 204
196
```
197
198
### Media Type Utilities
199
200
Utilities for handling media types and content negotiation.
201
202
```python { .api }
203
class MediaTypeDict(dict):
204
"""
205
Dictionary subclass for media type mapping with wildcard support.
206
"""
207
208
def best_match(self, supported_types: list) -> str:
209
"""
210
Find best matching media type from supported types.
211
212
Parameters:
213
- supported_types: List of supported media types
214
215
Returns:
216
str: Best matching media type or None
217
"""
218
```
219
220
## Usage Examples
221
222
### Accessing Request Data
223
224
```python
225
from connexion.context import request
226
227
def create_user():
228
# Access JSON body
229
user_data = request.json
230
231
# Access form data
232
form_data = request.form
233
234
# Access uploaded files
235
uploaded_file = request.files.get('avatar')
236
237
# Access query parameters
238
page = request.args.get('page', 1)
239
240
# Access headers
241
auth_header = request.headers.get('Authorization')
242
243
return {"status": "created"}, 201
244
```
245
246
### Custom Response Handling
247
248
```python
249
from connexion import NoContent
250
from connexion.lifecycle import ConnexionResponse
251
252
def update_user(user_id: int):
253
# Return different response types
254
if not user_exists(user_id):
255
return {"error": "User not found"}, 404
256
257
# Update user...
258
259
# Return empty response
260
return NoContent, 204
261
262
def get_user_avatar(user_id: int):
263
# Return binary content with custom headers
264
avatar_data = get_avatar_bytes(user_id)
265
266
return ConnexionResponse(
267
body=avatar_data,
268
status_code=200,
269
headers={'Content-Type': 'image/jpeg'},
270
content_type='image/jpeg'
271
)
272
```
273
274
### Problem Responses
275
276
```python
277
from connexion import problem
278
279
def validate_user_input(user_data):
280
if not user_data.get('email'):
281
return problem(
282
status=400,
283
title="Missing Required Field",
284
detail="Email address is required",
285
type="https://api.example.com/problems/missing-field",
286
field="email"
287
)
288
289
if not is_valid_email(user_data['email']):
290
return problem(
291
status=400,
292
title="Invalid Email Format",
293
detail=f"'{user_data['email']}' is not a valid email address",
294
type="https://api.example.com/problems/invalid-format",
295
field="email",
296
value=user_data['email']
297
)
298
299
return None # No problems
300
```
301
302
### Content Negotiation
303
304
```python
305
from connexion.lifecycle import ConnexionRequest, ConnexionResponse
306
307
def get_data():
308
# Check Accept header for content negotiation
309
if request.headers.get('Accept') == 'application/xml':
310
xml_data = convert_to_xml(data)
311
return ConnexionResponse(
312
body=xml_data,
313
content_type='application/xml'
314
)
315
316
# Default to JSON
317
return {"data": "json format"}
318
```
319
320
### File Upload Handling
321
322
```python
323
def upload_file():
324
uploaded_file = request.files.get('file')
325
326
if not uploaded_file:
327
return problem(400, "No file uploaded")
328
329
# Validate file
330
if uploaded_file.content_type not in ['image/jpeg', 'image/png']:
331
return problem(
332
400,
333
"Invalid file type",
334
detail="Only JPEG and PNG images are allowed"
335
)
336
337
# Process file
338
file_path = save_uploaded_file(uploaded_file)
339
340
return {"file_path": file_path, "size": len(uploaded_file.read())}, 201
341
```