From e9b76946b7aba10dabf5cf2176deeedf5c01a8f8 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 20 Dec 2021 09:11:56 +0100 Subject: [PATCH 1/6] docs: add new not_found feature --- docs/core/event_handler/api_gateway.md | 42 ++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 1f5fa4479c0..45f6ac46ab2 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -478,6 +478,48 @@ Similarly to [Query strings](#query-strings-and-payload), you can access headers return app.resolve(event, context) ``` + +### Handling not found routes + +By default, Event Handler handles not found routes by simply returning 404 with `Not found` text. + +If you'd like to handle it any differently, you can use `not_found` decorator. + +```python +from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, Response +from aws_lambda_powertools.event_handler.exceptions import NotFoundError + +tracer = Tracer() +logger = Logger() +app = ApiGatewayResolver() + +@app.not_found +@tracer.capture_method +def handle_not_found_errors(exc: NotFoundError) -> Response: + # Return 418 upon 404 errors + logger.info(f"Not found route: {app.current_event.path}") + return Response(status_code=418, content_type=content_types.TEXT_PLAIN, body="I'm a teapot!") + + +@app.get("/catch/me/if/you/can") +@tracer.capture_method +def catch_me_if_you_can(): + return {"message": "oh hey"} + +# You can continue to use other utilities just as before +@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) +@tracer.capture_lambda_handler +def lambda_handler(event, context): + return app.resolve(event, context) +``` + + +### Exception handling + + + ### Raising HTTP errors You can easily raise any HTTP Error back to the client using `ServiceError` exception. From bfbaad7994ecf6220b628b60939c6cfdc6209c70 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 20 Dec 2021 09:19:26 +0100 Subject: [PATCH 2/6] chore: highlight and wording --- docs/core/event_handler/api_gateway.md | 72 ++++++++++++++------------ 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 45f6ac46ab2..772b6d4fc58 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -481,39 +481,45 @@ Similarly to [Query strings](#query-strings-and-payload), you can access headers ### Handling not found routes -By default, Event Handler handles not found routes by simply returning 404 with `Not found` text. - -If you'd like to handle it any differently, you can use `not_found` decorator. - -```python -from aws_lambda_powertools import Logger, Tracer -from aws_lambda_powertools.logging import correlation_paths -from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, Response -from aws_lambda_powertools.event_handler.exceptions import NotFoundError - -tracer = Tracer() -logger = Logger() -app = ApiGatewayResolver() - -@app.not_found -@tracer.capture_method -def handle_not_found_errors(exc: NotFoundError) -> Response: - # Return 418 upon 404 errors - logger.info(f"Not found route: {app.current_event.path}") - return Response(status_code=418, content_type=content_types.TEXT_PLAIN, body="I'm a teapot!") - - -@app.get("/catch/me/if/you/can") -@tracer.capture_method -def catch_me_if_you_can(): - return {"message": "oh hey"} - -# You can continue to use other utilities just as before -@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) -@tracer.capture_lambda_handler -def lambda_handler(event, context): - return app.resolve(event, context) -``` +By default, we return `404` for any unmatched route. + +You can use **`not_found`** decorator to override this behaviour, and return a custom **`Response`**. + +=== "app.py" + + ```python hl_lines="10 12 15" title="Handling not found" + from aws_lambda_powertools import Logger, Tracer + from aws_lambda_powertools.logging import correlation_paths + from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, Response + from aws_lambda_powertools.event_handler.exceptions import NotFoundError + + tracer = Tracer() + logger = Logger() + app = ApiGatewayResolver() + + @app.not_found + @tracer.capture_method + def handle_not_found_errors(exc: NotFoundError) -> Response: + # Return 418 upon 404 errors + logger.info(f"Not found route: {app.current_event.path}") + return Response( + status_code=418, + content_type=content_types.TEXT_PLAIN, + body="I'm a teapot!" + ) + + + @app.get("/catch/me/if/you/can") + @tracer.capture_method + def catch_me_if_you_can(): + return {"message": "oh hey"} + + # You can continue to use other utilities just as before + @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) + @tracer.capture_lambda_handler + def lambda_handler(event, context): + return app.resolve(event, context) + ``` ### Exception handling From d3fb439e3aa63d29e79bb86f2fec4771bb359509 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 20 Dec 2021 09:39:25 +0100 Subject: [PATCH 3/6] docs: add exception handling section --- docs/core/event_handler/api_gateway.md | 45 ++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 772b6d4fc58..0999929a7ff 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -487,9 +487,10 @@ You can use **`not_found`** decorator to override this behaviour, and return a c === "app.py" - ```python hl_lines="10 12 15" title="Handling not found" + ```python hl_lines="11 13 16" title="Handling not found" from aws_lambda_powertools import Logger, Tracer from aws_lambda_powertools.logging import correlation_paths + from aws_lambda_powertools.event_handler import content_types from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, Response from aws_lambda_powertools.event_handler.exceptions import NotFoundError @@ -514,7 +515,6 @@ You can use **`not_found`** decorator to override this behaviour, and return a c def catch_me_if_you_can(): return {"message": "oh hey"} - # You can continue to use other utilities just as before @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) @tracer.capture_lambda_handler def lambda_handler(event, context): @@ -524,6 +524,47 @@ You can use **`not_found`** decorator to override this behaviour, and return a c ### Exception handling +You might want to handle an exception outside your route like custom validation errors or anything that warrants a different response (status code, headers, body). + +You can use `exception_handler` decorator with any Python exception. + +=== "app.py" + + ```python hl_lines="10 15" title="Exception handling" + from aws_lambda_powertools import Logger, Tracer + from aws_lambda_powertools.logging import correlation_paths + from aws_lambda_powertools.event_handler import content_types + from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, Response + + tracer = Tracer() + logger = Logger() + app = ApiGatewayResolver() + + @app.exception_handler(ValueError) + def handle_value_error(ex: ValueError): + metadata = {"path": app.current_event.path} + logger.error(f"Malformed request: {ex}", extra=metadata) + + return Response( + status_code=400, + content_type=content_types.TEXT_PLAIN, + body="Invalid request", + ) + + + @app.get("/hello") + @tracer.capture_method + def hello_name(): + name = app.current_event.get_query_string_value(name="name") + if name is not None: + raise ValueError("name query string must be present") + return {"message": f"hello {name}"} + + @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST) + @tracer.capture_lambda_handler + def lambda_handler(event, context): + return app.resolve(event, context) + ``` ### Raising HTTP errors From 47c27332ac72d194ebb9f99e3eb0b2014d8132c0 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 20 Dec 2021 09:40:22 +0100 Subject: [PATCH 4/6] docs: enable instant loading due to doc size --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 511cefb5e67..218deea586b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -49,6 +49,7 @@ theme: - navigation.sections - navigation.expand - navigation.top + - navigation.instant icon: repo: fontawesome/brands/github logo: media/aws-logo-light.svg From ac897733e289a2fd39f7c140d2596647d4d8e6d0 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 20 Dec 2021 09:42:04 +0100 Subject: [PATCH 5/6] chore: improve wording on exception handling --- docs/core/event_handler/api_gateway.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 0999929a7ff..8926b54db87 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -524,9 +524,7 @@ You can use **`not_found`** decorator to override this behaviour, and return a c ### Exception handling -You might want to handle an exception outside your route like custom validation errors or anything that warrants a different response (status code, headers, body). - -You can use `exception_handler` decorator with any Python exception. +You can use `exception_handler` decorator with any Python exception. This allows you to handle a common exception outside your route, for example validation errors. === "app.py" From 079fcbf78326f3224a4c9be8181c76b5f714e484 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 20 Dec 2021 09:42:36 +0100 Subject: [PATCH 6/6] chore: bold --- docs/core/event_handler/api_gateway.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 8926b54db87..cb06aa37841 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -524,7 +524,7 @@ You can use **`not_found`** decorator to override this behaviour, and return a c ### Exception handling -You can use `exception_handler` decorator with any Python exception. This allows you to handle a common exception outside your route, for example validation errors. +You can use **`exception_handler`** decorator with any Python exception. This allows you to handle a common exception outside your route, for example validation errors. === "app.py"