Skip to content

Commit f0ebc80

Browse files
Adding docs + small fix in tests
1 parent c330e43 commit f0ebc80

File tree

4 files changed

+90
-7
lines changed

4 files changed

+90
-7
lines changed

docs/core/event_handler/api_gateway.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Event handler for Amazon API Gateway REST and HTTP APIs, Application Load Balanc
1111
* Support for CORS, binary and Gzip compression, Decimals JSON encoding and bring your own JSON serializer
1212
* Built-in integration with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank"} for self-documented event schema
1313
* Works with micro function (one or a few routes) and monolithic functions (all routes)
14+
* Support for Middleware
1415
* Support for OpenAPI schema generation
1516
* Support data validation for requests/responses
1617

@@ -303,7 +304,7 @@ If you need to accept multiple HTTP methods in a single function, or support a H
303304

304305
For brevity, we'll focus on Pydantic only.
305306

306-
All resolvers can optionally coerce and validate incoming requests by setting `enable_validation=True`.
307+
All resolvers can optionally coerce and validate incoming requests by setting `enable_validation=True`. You can use Pydantic models to validate request bodies, query strings, headers, and form parameters.
307308

308309
With this feature, we can now express how we expect our incoming data and response to look like. This moves data validation responsibilities to Event Handler resolvers, reducing a ton of boilerplate code.
309310

@@ -519,6 +520,16 @@ In the following example, we use a new `Query` OpenAPI type to add [one out of m
519520

520521
1. `example_multi_value_param` is a list containing values from the `ExampleEnum` enumeration.
521522

523+
=== "validating_query_string_with_pydantic.py"
524+
525+
You can use Pydantic models to define your query string parameters.
526+
527+
```python hl_lines="18-22 27"
528+
--8<-- "examples/event_handler_rest/src/validating_query_string_with_pydantic.py"
529+
```
530+
531+
1. `todo` is a Pydantic model.
532+
522533
<!-- markdownlint-enable MD013 -->
523534

524535
#### Validating path parameters
@@ -567,6 +578,16 @@ In the following example, we use a new `Header` OpenAPI type to add [one out of
567578

568579
1. `cloudfront_viewer_country` is a list that must contain values from the `CountriesAllowed` enumeration.
569580

581+
=== "validating_headers_with_pydantic.py"
582+
583+
You can use Pydantic models to define your headers parameters.
584+
585+
```python hl_lines="18-22 27"
586+
--8<-- "examples/event_handler_rest/src/validating_headers_with_pydantic.py"
587+
```
588+
589+
1. `todo` is a Pydantic model.
590+
570591
#### Handling form data
571592

572593
!!! info "You must set `enable_validation=True` to handle file uploads and form data via type annotation."
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from typing import Any, Dict, Optional
2+
3+
from pydantic import BaseModel, Field
4+
from typing_extensions import Annotated
5+
6+
from aws_lambda_powertools import Logger, Tracer
7+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
8+
from aws_lambda_powertools.event_handler.openapi.params import Header
9+
from aws_lambda_powertools.logging import correlation_paths
10+
from aws_lambda_powertools.utilities.typing import LambdaContext
11+
12+
tracer = Tracer()
13+
logger = Logger()
14+
app = APIGatewayRestResolver(enable_validation=True)
15+
16+
17+
class Todo(BaseModel):
18+
userId: int
19+
id_: Optional[int] = Field(alias="id", default=None)
20+
title: str
21+
completed: bool
22+
23+
24+
@app.get("/todos")
25+
@tracer.capture_method
26+
def get_todos(todo: Annotated[Todo, Header()]) -> Dict[str, Any]: # (1)!
27+
return todo.model_dump()
28+
29+
30+
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
31+
@tracer.capture_lambda_handler
32+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
33+
return app.resolve(event, context)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from typing import Any, Dict, Optional
2+
3+
from pydantic import BaseModel, Field
4+
from typing_extensions import Annotated
5+
6+
from aws_lambda_powertools import Logger, Tracer
7+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
8+
from aws_lambda_powertools.event_handler.openapi.params import Query
9+
from aws_lambda_powertools.logging import correlation_paths
10+
from aws_lambda_powertools.utilities.typing import LambdaContext
11+
12+
tracer = Tracer()
13+
logger = Logger()
14+
app = APIGatewayRestResolver(enable_validation=True)
15+
16+
17+
class Todo(BaseModel):
18+
userId: int
19+
id_: Optional[int] = Field(alias="id", default=None)
20+
title: str
21+
completed: bool
22+
23+
24+
@app.get("/todos")
25+
@tracer.capture_method
26+
def get_todos(todo: Annotated[Todo, Query()]) -> Dict[str, Any]: # (1)!
27+
return todo.model_dump()
28+
29+
30+
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
31+
@tracer.capture_lambda_handler
32+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
33+
return app.resolve(event, context)

tests/functional/event_handler/_pydantic/test_openapi_validation_middleware.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
from dataclasses import dataclass
44
from enum import Enum
55
from pathlib import PurePath
6-
from typing import Dict, List, Literal, Optional, Tuple, Union
6+
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
77

88
import pytest
9-
from pydantic import BaseModel, Field
9+
from pydantic import AfterValidator, Base64UrlStr, BaseModel, ConfigDict, Field, StringConstraints, alias_generators
1010
from typing_extensions import Annotated
1111

1212
from aws_lambda_powertools.event_handler import (
@@ -2542,15 +2542,11 @@ def create_action(action: Annotated[action_type, Body()]):
25422542

25432543
def test_validate_pydantic_query_params_with_config_dict_and_validators(gw_event):
25442544
"""Test that Pydantic models with ConfigDict, aliases, and validators work correctly"""
2545-
from typing import Any
2546-
2547-
from pydantic import AfterValidator, Base64UrlStr, ConfigDict, StringConstraints, alias_generators
25482545

25492546
del gw_event["multiValueHeaders"]
25502547
del gw_event["multiValueQueryStringParameters"]
25512548

25522549
app = APIGatewayRestResolver(enable_validation=True)
2553-
app.enable_swagger(path="/swagger")
25542550

25552551
def _validate_powertools(value: str) -> str:
25562552
if not value.startswith("Powertools"):

0 commit comments

Comments
 (0)