diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index 87433b020d5..ce767e8a4ee 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -1222,6 +1222,63 @@ def lambda_handler(event, context): middlewares, ) + def head( + self, + rule: str, + cors: Optional[bool] = None, + compress: bool = False, + cache_control: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + responses: Optional[Dict[int, OpenAPIResponse]] = None, + response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION, + tags: Optional[List[str]] = None, + operation_id: Optional[str] = None, + include_in_schema: bool = True, + security: Optional[List[Dict[str, List[str]]]] = None, + middlewares: Optional[List[Callable]] = None, + ): + """Head route decorator with HEAD `method` + + Examples + -------- + Simple example with a custom lambda handler using the Tracer capture_lambda_handler decorator + + ```python + from aws_lambda_powertools import Tracer + from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response, content_types + + tracer = Tracer() + app = APIGatewayRestResolver() + + @app.head("/head-call") + def simple_head(): + return Response(status_code=200, + content_type=content_types.APPLICATION_JSON, + headers={"Content-Length": "123"}) + + @tracer.capture_lambda_handler + def lambda_handler(event, context): + return app.resolve(event, context) + ``` + """ + return self.route( + rule, + "HEAD", + cors, + compress, + cache_control, + summary, + description, + responses, + response_description, + tags, + operation_id, + include_in_schema, + security, + middlewares, + ) + def _push_processed_stack_frame(self, frame: str): """ Add Current Middleware to the Middleware Stack Frames diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index aaf9352ebc0..32789ec09e2 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -221,7 +221,7 @@ You can use named decorators to specify the HTTP method that should be handled i --8<-- "examples/event_handler_rest/src/http_methods.json" ``` -If you need to accept multiple HTTP methods in a single function, you can use the `route` method and pass a list of HTTP methods. +If you need to accept multiple HTTP methods in a single function, or support a HTTP method for which no decorator exists (e.g. [TRACE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/TRACE)), you can use the `route` method and pass a list of HTTP methods. ```python hl_lines="15" title="Handling multiple HTTP Methods" --8<-- "examples/event_handler_rest/src/http_methods_multiple.py" @@ -524,12 +524,12 @@ Behind the scenes, the [data validation](#data-validation) feature auto-generate There are some important **caveats** that you should know before enabling it: -| Caveat | Description | -| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Swagger UI is **publicly accessible by default** | When using `enable_swagger` method, you can [protect sensitive API endpoints by implementing a custom middleware](#customizing-swagger-ui) using your preferred authorization mechanism. | -| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. | -| You need to expose a **new route** | You'll need to expose the following path to Lambda: `/swagger`; ignore if you're routing this path already. | -| JS and CSS files are **embedded within Swagger HTML** | If you are not using an external CDN to serve Swagger UI assets, we embed JS and CSS directly into the HTML. To enhance performance, please consider enabling the `compress` option to minimize the size of HTTP requests. | +| Caveat | Description | +| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Swagger UI is **publicly accessible by default** | When using `enable_swagger` method, you can [protect sensitive API endpoints by implementing a custom middleware](#customizing-swagger-ui) using your preferred authorization mechanism. | +| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. | +| You need to expose a **new route** | You'll need to expose the following path to Lambda: `/swagger`; ignore if you're routing this path already. | +| JS and CSS files are **embedded within Swagger HTML** | If you are not using an external CDN to serve Swagger UI assets, we embed JS and CSS directly into the HTML. To enhance performance, please consider enabling the `compress` option to minimize the size of HTTP requests. | ```python hl_lines="12-13" title="enabling_swagger.py" --8<-- "examples/event_handler_rest/src/enabling_swagger.py" @@ -835,8 +835,8 @@ As a practical example, let's refactor our correlation ID middleware so it accep These are native middlewares that may become native features depending on customer demand. -| Middleware | Purpose | -| ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | +| Middleware | Purpose | +| ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | [SchemaValidationMiddleware](/lambda/python/latest/api/event_handler/middlewares/schema_validation.html){target="_blank"} | Validates API request body and response against JSON Schema, using [Validation utility](../../utilities/validation.md){target="_blank"} | #### Being a good citizen @@ -1053,7 +1053,7 @@ When you're describing your API, declare security schemes at the top level, and OpenAPI 3 lets you describe APIs protected using the following security schemes: | Security Scheme | Type | Description | -|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [HTTP auth](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml){target="_blank"} | `HTTPBase` | HTTP authentication schemes using the Authorization header (e.g: [Basic auth](https://swagger.io/docs/specification/authentication/basic-authentication/){target="_blank"}, [Bearer](https://swagger.io/docs/specification/authentication/bearer-authentication/){target="_blank"}) | | [API keys](https://swagger.io/docs/specification/authentication/api-keys/https://swagger.io/docs/specification/authentication/api-keys/){target="_blank"} (e.g: query strings, cookies) | `APIKey` | API keys in headers, query strings or [cookies](https://swagger.io/docs/specification/authentication/cookie-authentication/){target="_blank"}. | | [OAuth 2](https://swagger.io/docs/specification/authentication/oauth2/){target="_blank"} | `OAuth2` | Authorization protocol that gives an API client limited access to user data on a web server. | diff --git a/tests/functional/event_handler/test_api_gateway.py b/tests/functional/event_handler/test_api_gateway.py index 3929496be50..14af1ad175e 100644 --- a/tests/functional/event_handler/test_api_gateway.py +++ b/tests/functional/event_handler/test_api_gateway.py @@ -291,12 +291,16 @@ def delete_func(): def patch_func(): raise RuntimeError() + @app.head("/no_matching_head") + def head_func(): + raise RuntimeError() + def handler(event, context): return app.resolve(event, context) # Also check the route configurations routes = app._static_routes - assert len(routes) == 5 + assert len(routes) == 6 for route in routes: if route.func == get_func: assert route.method == "GET" @@ -308,6 +312,8 @@ def handler(event, context): assert route.method == "DELETE" elif route.func == patch_func: assert route.method == "PATCH" + elif route.func == head_func: + assert route.method == "HEAD" # WHEN calling the handler # THEN return a 404