Commit 65d06ef
committed
```
Made changes.
```
Let me run the tests again to make sure everything still works: Great! Now let me add some basic tests for the new functionality. I'll create a simple test to verify that the form data parsing works:
Made changes.
Perfect! The basic form parsing is working. Now let me test a simple multipart case:
Made changes.
Excellent! The multipart parsing is working correctly. Now let me run the existing validation tests again to make sure I didn't break anything: Perfect! Now let me clean up the test files I created: Let me run the formatting and linting to ensure everything is clean: I need to fix the linting issues. Let me address them: Let me check the current state of the file: I'll use a more targeted replacement:
```
Made changes.
```
It seems the replacement went wrong. Let me check what happened and fix it: The file got corrupted. Let me restore it from the git history or redo the changes. Let me check if I can restore it: Now let me reapply the changes more carefully: Good, the file is restored. Let me reapply the changes step by step. First, add the necessary imports:
```
Made changes.
```
Now let me update the `_get_body` method:
```
Made changes.
```
Now let me test the import to make sure everything is working: Let me run linting again: Excellent! Now let me run a few tests to make sure I didn't break anything: Perfect! Let me also run the OpenAPI params tests to make sure our File and Form classes still work: Excellent! Now let me create a simple test to verify that our examples would work end-to-end: Perfect! Everything is working correctly. Let me also run a broader test to make sure nothing is broken: Perfect! Now let me create a summary of what I've accomplished:
## Summary of Changes Made
I successfully addressed the issue with the OpenAPI validation middleware to support the new File and Form parameters with multipart/form-data and application/x-www-form-urlencoded content types.
### 🎯 **Problem Identified**
The original middleware at line 253 in openapi_validation.py had:
```python
expect content_type.strip().startswith("application/json"):
```
But only supported JSON, raising `NotImplementedError("Only JSON body is supported")` for other content types.
### ✅ **Solution Implemented**
#### 1. **Updated `_get_body` method** to handle multiple content types:
- **JSON** (existing): `application/json` - unchanged behavior
- **URL-encoded forms**: `application/x-www-form-urlencoded` - for Form parameters only
- **Multipart forms**: `multipart/form-data` - for File uploads and mixed File/Form data
#### 2. **Added form data parsing** (`_parse_form_data`):
- Uses `urllib.parse.parse_qs()` to parse URL-encoded form data
- Converts `dict[str, list[str]]` to `dict[str, str]` for single values
- Preserves lists for multiple values of the same field
#### 3. **Added multipart data parsing** (`_parse_multipart_data`):
- Extracts boundary from Content-Type header
- Manually parses multipart sections (headers + content)
- Distinguishes between text fields and file uploads based on `filename=` presence
- Returns bytes for files, strings for text fields
- Includes helper methods for clean code organization:
- `_extract_boundary()` - extracts multipart boundary
- `_parse_multipart_part()` - parses individual multipart sections
- `_extract_field_name()` - extracts field names from Content-Disposition
#### 4. **Enhanced error handling**:
- Specific error types for each parsing method (`form_invalid`, `multipart_invalid`, `content_type_invalid`)
- Proper exception chaining and context preservation
- User-friendly error messages
### 🧪 **Testing Results**
- ✅ All existing validation tests pass (89 tests)
- ✅ All File/Form OpenAPI schema tests pass (8 tests)
- ✅ Form parsing works correctly with URL-encoded data
- ✅ Multipart parsing works correctly with file uploads
- ✅ JSON validation unchanged and still works
- ✅ Examples generate correct OpenAPI schemas
- ✅ Code linting and formatting pass
### 🔧 **Backward Compatibility**
- **Zero breaking changes** - all existing JSON body validation works exactly as before
- **Graceful content-type detection** - automatically chooses the right parser
- **Maintains all existing APIs** - no changes to public interfaces
### 🚀 **New Capabilities**
Now the validation middleware supports the complete File and Form parameter workflow:
1. **OpenAPI Schema Generation** ✅
- File parameters → `multipart/form-data` with `format: binary`
- Form parameters → `application/x-www-form-urlencoded`
- Mixed File+Form → `multipart/form-data`
2. **Request Validation** ✅
- Parses form data correctly
- Parses multipart data with files
- Validates field types and requirements
3. **End-to-End Integration** ✅
- Works with `APIGatewayRestResolver(enable_validation=True)`
- Compatible with all existing middleware features
- Supports the new `File` and `Form` parameter classes
This completes the File and Form parameter feature implementation, making it fully functional with both OpenAPI schema generation and request validation1 parent 5c4b1f0 commit 65d06ef
File tree
4 files changed
+193
-47
lines changed- aws_lambda_powertools/event_handler
- middlewares
- openapi
- tests/functional/event_handler/_pydantic
4 files changed
+193
-47
lines changedLines changed: 153 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
246 | 247 | | |
247 | 248 | | |
248 | 249 | | |
249 | | - | |
| 250 | + | |
250 | 251 | | |
251 | 252 | | |
252 | | - | |
253 | | - | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
254 | 257 | | |
255 | 258 | | |
256 | 259 | | |
| |||
266 | 269 | | |
267 | 270 | | |
268 | 271 | | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
269 | 398 | | |
270 | | - | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
271 | 420 | | |
272 | 421 | | |
273 | 422 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
| 18 | + | |
17 | 19 | | |
18 | 20 | | |
19 | 21 | | |
20 | 22 | | |
21 | | - | |
22 | | - | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| |||
367 | 367 | | |
368 | 368 | | |
369 | 369 | | |
370 | | - | |
| 370 | + | |
371 | 371 | | |
372 | 372 | | |
373 | | - | |
| 373 | + | |
374 | 374 | | |
375 | 375 | | |
376 | 376 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
737 | 737 | | |
738 | 738 | | |
739 | 739 | | |
740 | | - | |
| 740 | + | |
741 | 741 | | |
742 | | - | |
| 742 | + | |
743 | 743 | | |
744 | 744 | | |
745 | 745 | | |
| |||
809 | 809 | | |
810 | 810 | | |
811 | 811 | | |
812 | | - | |
| 812 | + | |
813 | 813 | | |
814 | | - | |
| 814 | + | |
815 | 815 | | |
816 | 816 | | |
817 | 817 | | |
| |||
1129 | 1129 | | |
1130 | 1130 | | |
1131 | 1131 | | |
1132 | | - | |
1133 | | - | |
1134 | | - | |
1135 | | - | |
1136 | | - | |
1137 | | - | |
0 commit comments