Skip to content

Commit 558c03c

Browse files
Refactoring documentation
1 parent bd93ee6 commit 558c03c

File tree

6 files changed

+63
-51
lines changed

6 files changed

+63
-51
lines changed

aws_lambda_powertools/event_handler/api_gateway.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1586,7 +1586,6 @@ def _validate_response_validation_error_http_code(
15861586
else HTTPStatus.UNPROCESSABLE_ENTITY
15871587
)
15881588

1589-
15901589
def get_openapi_schema(
15911590
self,
15921591
*,

docs/core/event_handler/api_gateway.md

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,6 @@ Here's an example where we catch validation errors, log all details for further
321321

322322
=== "data_validation_sanitized_error.py"
323323

324-
Note that Pydantic versions [1](https://docs.pydantic.dev/1.10/usage/models/#error-handling){target="_blank" rel="nofollow"} and [2](https://docs.pydantic.dev/latest/errors/errors/){target="_blank" rel="nofollow"} report validation detailed errors differently.
325-
326324
```python hl_lines="8 24-25 31"
327325
--8<-- "examples/event_handler_rest/src/data_validation_sanitized_error.py"
328326
```
@@ -400,32 +398,24 @@ We use the `Annotated` and OpenAPI `Body` type to instruct Event Handler that ou
400398

401399
#### Validating responses
402400

403-
The optional `response_validation_error_http_code` argument can be set for all the resolvers to distinguish between failed data validation of payload and response. The desired HTTP status code for failed response validation must be passed to this argument.
404-
405-
Following on from our previous example, we want to distinguish between an invalid payload sent by the user and an invalid response which is being proxying to the user from another endpoint.
401+
You can use `response_validation_error_http_code` to set a custom HTTP code for failed response validation. When this field is set, we will raise a `ResponseValidationError` instead of a `RequestValidationError`.
406402

407403
=== "customizing_response_validation.py"
408404

409-
```python hl_lines="18 30 34 36"
405+
```python hl_lines="1 16 29 33"
410406
--8<-- "examples/event_handler_rest/src/customizing_response_validation.py"
411407
```
412408

413-
1. This enforces response data validation at runtime. A response with status code set here will be returned if response data is not valid.
414-
2. We validate our response body against `Todo`.
415-
3. Operation returns a string as oppose to a Todo object. This will lead to a `500` response as set in line 18.
416-
4. The distinct `ResponseValidationError` exception can be caught to customise the response—see difference between the sanitized and unsanitized responses.
409+
1. A response with status code set here will be returned if response data is not valid.
410+
2. Operation returns a string as oppose to a `Todo` object. This will lead to a `500` response as set in line 18.
417411

418-
=== "sanitized_error_response.json"
412+
=== "customizing_response_validation_exception.py"
419413

420-
```json hl_lines="2-3"
421-
--8<-- "examples/event_handler_rest/src/response_validation_sanitized_error_output.json"
414+
```python hl_lines="1 18 38 39"
415+
--8<-- "examples/event_handler_rest/src/customizing_response_validation_exception.py"
422416
```
423417

424-
=== "unsanitized_error_response.json"
425-
426-
```json hl_lines="2-3"
427-
--8<-- "examples/event_handler_rest/src/response_validation_error_unsanitized_output.json"
428-
```
418+
1. The distinct `ResponseValidationError` exception can be caught to customise the response.
429419

430420
#### Validating query strings
431421

examples/event_handler_rest/src/customizing_response_validation.py

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
from pydantic import BaseModel, Field
66

77
from aws_lambda_powertools import Logger, Tracer
8-
from aws_lambda_powertools.event_handler import APIGatewayRestResolver, content_types
9-
from aws_lambda_powertools.event_handler.api_gateway import Response
10-
from aws_lambda_powertools.event_handler.openapi.exceptions import ResponseValidationError
8+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
119
from aws_lambda_powertools.logging import correlation_paths
1210
from aws_lambda_powertools.utilities.typing import LambdaContext
1311

@@ -28,22 +26,11 @@ class Todo(BaseModel):
2826

2927
@app.get("/todos_bad_response/<todo_id>")
3028
@tracer.capture_method
31-
def get_todo_by_id(todo_id: int) -> Todo: # (2)!
29+
def get_todo_by_id(todo_id: int) -> Todo:
3230
todo = requests.get(f"https://jsonplaceholder.typicode.com/todos/{todo_id}")
3331
todo.raise_for_status()
3432

35-
return todo.json()["title"] # (3)!
36-
37-
38-
@app.exception_handler(ResponseValidationError) # (4)!
39-
def handle_response_validation_error(ex: ResponseValidationError):
40-
logger.error("Request failed validation", path=app.current_event.path, errors=ex.errors())
41-
42-
return Response(
43-
status_code=500,
44-
content_type=content_types.APPLICATION_JSON,
45-
body="Unexpected response.",
46-
)
33+
return todo.json()["title"] # (2)!
4734

4835

4936
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from http import HTTPStatus
2+
from typing import Optional
3+
4+
import requests
5+
from pydantic import BaseModel, Field
6+
7+
from aws_lambda_powertools import Logger, Tracer
8+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver, content_types
9+
from aws_lambda_powertools.event_handler.api_gateway import Response
10+
from aws_lambda_powertools.event_handler.openapi.exceptions import ResponseValidationError
11+
from aws_lambda_powertools.logging import correlation_paths
12+
from aws_lambda_powertools.utilities.typing import LambdaContext
13+
14+
tracer = Tracer()
15+
logger = Logger()
16+
app = APIGatewayRestResolver(
17+
enable_validation=True,
18+
response_validation_error_http_code=HTTPStatus.INTERNAL_SERVER_ERROR,
19+
)
20+
21+
22+
class Todo(BaseModel):
23+
userId: int
24+
id_: Optional[int] = Field(alias="id", default=None)
25+
title: str
26+
completed: bool
27+
28+
29+
@app.get("/todos_bad_response/<todo_id>")
30+
@tracer.capture_method
31+
def get_todo_by_id(todo_id: int) -> Todo:
32+
todo = requests.get(f"https://jsonplaceholder.typicode.com/todos/{todo_id}")
33+
todo.raise_for_status()
34+
35+
return todo.json()["title"]
36+
37+
38+
@app.exception_handler(ResponseValidationError) # (1)!
39+
def handle_response_validation_error(ex: ResponseValidationError):
40+
logger.error("Request failed validation", path=app.current_event.path, errors=ex.errors())
41+
42+
return Response(
43+
status_code=500,
44+
content_type=content_types.APPLICATION_JSON,
45+
body="Unexpected response.",
46+
)
47+
48+
49+
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
50+
@tracer.capture_lambda_handler
51+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
52+
return app.resolve(event, context)

examples/event_handler_rest/src/response_validation_error_unsanitized_output.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

examples/event_handler_rest/src/response_validation_sanitized_error_output.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)