Commit c83d15e
feat(event_handler): add support for form data in OpenAPI utility (#7028)
* chore(openapi): add FileSchema & HeaderParamSchema helpers
* chore(openapi): leave FileSchema only (header already supported)
* feat(openapi): add multipart/form-data & form support
* feat(openapi): add multipart/form-data & form support- documentation
* run make format
* add comprehensive tests for File/Form OpenAPI support
* make format
* additional test cases
* ```
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 validation
* defined a constant for the "name=" literal to avoid duplication in the OpenAPI validation middleware
* make fmt
* sonar suggestion fix
* Added Comprehensive Test Coverage
* make format
* full test suite completed
* Refactoring and removing Form
* Refactoring and removing Form
---------
Co-authored-by: Leandro Damascena <lcdama@amazon.pt>1 parent 47c08ce commit c83d15e
File tree
7 files changed
+391
-72
lines changed- aws_lambda_powertools/event_handler
- middlewares
- openapi
- docs/core/event_handler
- examples/event_handler_rest/src
- tests/functional/event_handler/_pydantic
7 files changed
+391
-72
lines changedLines changed: 58 additions & 19 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
33 | 39 | | |
34 | 40 | | |
35 | 41 | | |
| |||
246 | 252 | | |
247 | 253 | | |
248 | 254 | | |
249 | | - | |
| 255 | + | |
250 | 256 | | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
251 | 266 | | |
252 | | - | |
253 | | - | |
254 | | - | |
255 | | - | |
256 | | - | |
257 | | - | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
266 | | - | |
267 | | - | |
268 | | - | |
269 | 267 | | |
270 | | - | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 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 | + | |
271 | 310 | | |
272 | 311 | | |
273 | 312 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
22 | | - | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| |||
348 | 348 | | |
349 | 349 | | |
350 | 350 | | |
| 351 | + | |
351 | 352 | | |
352 | 353 | | |
353 | 354 | | |
| |||
369 | 370 | | |
370 | 371 | | |
371 | 372 | | |
372 | | - | |
373 | | - | |
374 | | - | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
375 | 376 | | |
376 | 377 | | |
377 | 378 | | |
| |||
| 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 | | |
| |||
848 | 848 | | |
849 | 849 | | |
850 | 850 | | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
851 | 859 | | |
852 | 860 | | |
853 | 861 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
523 | 523 | | |
524 | 524 | | |
525 | 525 | | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
526 | 538 | | |
527 | 539 | | |
528 | 540 | | |
| |||
Lines changed: 19 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
Lines changed: 128 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
| |||
649 | 650 | | |
650 | 651 | | |
651 | 652 | | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
0 commit comments