AWS powertools documentation change
Summary
Added documentation for handling file uploads and accessing the Request object in AWS Lambda Powertools Event Handler
Security assessment
The changes add documentation for new features (file upload handling and Request object access) without addressing any specific security vulnerabilities. The file upload section includes a note about configuring Binary Media Types for API Gateway REST API (v1) to prevent binary file corruption, but this is a functional requirement rather than a security fix. No evidence of security vulnerabilities, patches, or incident response is present in the diff.
Diff
diff --git a/powertools/python/latest/core/event_handler/api_gateway.md b/powertools/python/latest/core/event_handler/api_gateway.md index c2f410066..5c5fefc97 100644 --- a//powertools/python/latest/core/event_handler/api_gateway.md +++ b//powertools/python/latest/core/event_handler/api_gateway.md @@ -71,0 +72 @@ Metrics + * Handling file uploads @@ -87,0 +89 @@ Metrics + * Accessing the Request object @@ -247,0 +250 @@ Table of contents + * Handling file uploads @@ -263,0 +267 @@ Table of contents + * Accessing the Request object @@ -4366,0 +4371,216 @@ working_with_form_data.py +#### Handling file uploads¶ + +You must set `enable_validation=True` to handle file uploads via type annotation. + +You can use the `File` type to accept `multipart/form-data` file uploads. This automatically sets the correct OpenAPI schema, and Swagger UI will render a file picker for each `File()` parameter. + +There are two ways to receive uploaded files: + + * **`bytes`** — receive raw file content only + * **`UploadFile`** — receive file content along with metadata (filename, content type) + + + +working_with_file_uploads.pyworking_with_file_uploads_metadata.pyworking_with_file_uploads_mixed.py + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + +| + + + from typing import Annotated + + from aws_lambda_powertools.event_handler import APIGatewayRestResolver + from aws_lambda_powertools.event_handler.openapi.params import File + + app = APIGatewayRestResolver(enable_validation=True) + + + @app.post("/upload") + def upload_file( + file_data: Annotated[bytes, File(description="File to upload")], # (1)! + ): + return {"file_size": len(file_data)} + + + def lambda_handler(event, context): + return app.resolve(event, context) + + +---|--- + + 1. `File` is a special OpenAPI type for `multipart/form-data` file uploads. When annotated as `bytes`, you receive the raw file content. + + + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + +| + + + from typing import Annotated + + from aws_lambda_powertools.event_handler import APIGatewayRestResolver + from aws_lambda_powertools.event_handler.openapi.params import File, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + + @app.post("/upload") + def upload_file( + file_data: Annotated[UploadFile, File(description="File to upload")], # (1)! + ): + return { + "filename": file_data.filename, # (2)! + "content_type": file_data.content_type, + "file_size": len(file_data), + } + + + def lambda_handler(event, context): + return app.resolve(event, context) + + +---|--- + + 1. Using `UploadFile` instead of `bytes` gives you access to file metadata. + 2. `filename` and `content_type` come from the multipart headers sent by the client. + + + +You can combine `File()` and `Form()` parameters in the same route to accept file uploads with additional form fields. + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + +| + + + import csv + import io + from typing import Annotated + + from aws_lambda_powertools.event_handler import APIGatewayRestResolver + from aws_lambda_powertools.event_handler.openapi.params import File, Form, UploadFile + + app = APIGatewayRestResolver(enable_validation=True) + + + @app.post("/upload-csv") + def upload_csv( + file_data: Annotated[UploadFile, File(description="CSV file to parse")], # (1)! + separator: Annotated[str, Form(description="CSV separator")] = ",", # (2)! + ): + text = file_data.content.decode("utf-8") + reader = csv.DictReader(io.StringIO(text), delimiter=separator) + rows = list(reader) + + return { + "filename": file_data.filename, + "total_rows": len(rows), + "columns": list(rows[0].keys()) if rows else [], + "data": rows, + } + + + def lambda_handler(event, context): + return app.resolve(event, context) + + +---|--- +