Skip to content

Commit 0412f66

Browse files
nlykkeigithub-actions[bot]aws-powertools-botleandrodamascena
authored
feat(event_handler): add decorator for HTTP HEAD verb (#4275)
chore(ci): changelog rebuild (#4262) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Powertools for AWS Lambda (Python) bot <[email protected]> Co-authored-by: Leandro Damascena <[email protected]>
1 parent f1cbcb3 commit 0412f66

File tree

3 files changed

+74
-11
lines changed

3 files changed

+74
-11
lines changed

Diff for: aws_lambda_powertools/event_handler/api_gateway.py

+57
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,63 @@ def lambda_handler(event, context):
12221222
middlewares,
12231223
)
12241224

1225+
def head(
1226+
self,
1227+
rule: str,
1228+
cors: Optional[bool] = None,
1229+
compress: bool = False,
1230+
cache_control: Optional[str] = None,
1231+
summary: Optional[str] = None,
1232+
description: Optional[str] = None,
1233+
responses: Optional[Dict[int, OpenAPIResponse]] = None,
1234+
response_description: str = _DEFAULT_OPENAPI_RESPONSE_DESCRIPTION,
1235+
tags: Optional[List[str]] = None,
1236+
operation_id: Optional[str] = None,
1237+
include_in_schema: bool = True,
1238+
security: Optional[List[Dict[str, List[str]]]] = None,
1239+
middlewares: Optional[List[Callable]] = None,
1240+
):
1241+
"""Head route decorator with HEAD `method`
1242+
1243+
Examples
1244+
--------
1245+
Simple example with a custom lambda handler using the Tracer capture_lambda_handler decorator
1246+
1247+
```python
1248+
from aws_lambda_powertools import Tracer
1249+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response, content_types
1250+
1251+
tracer = Tracer()
1252+
app = APIGatewayRestResolver()
1253+
1254+
@app.head("/head-call")
1255+
def simple_head():
1256+
return Response(status_code=200,
1257+
content_type=content_types.APPLICATION_JSON,
1258+
headers={"Content-Length": "123"})
1259+
1260+
@tracer.capture_lambda_handler
1261+
def lambda_handler(event, context):
1262+
return app.resolve(event, context)
1263+
```
1264+
"""
1265+
return self.route(
1266+
rule,
1267+
"HEAD",
1268+
cors,
1269+
compress,
1270+
cache_control,
1271+
summary,
1272+
description,
1273+
responses,
1274+
response_description,
1275+
tags,
1276+
operation_id,
1277+
include_in_schema,
1278+
security,
1279+
middlewares,
1280+
)
1281+
12251282
def _push_processed_stack_frame(self, frame: str):
12261283
"""
12271284
Add Current Middleware to the Middleware Stack Frames

Diff for: docs/core/event_handler/api_gateway.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ You can use named decorators to specify the HTTP method that should be handled i
221221
--8<-- "examples/event_handler_rest/src/http_methods.json"
222222
```
223223

224-
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.
224+
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.
225225

226226
```python hl_lines="15" title="Handling multiple HTTP Methods"
227227
--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
524524

525525
There are some important **caveats** that you should know before enabling it:
526526

527-
| Caveat | Description |
528-
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
529-
| 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. |
530-
| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. |
531-
| 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. |
532-
| 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. |
527+
| Caveat | Description |
528+
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
529+
| 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. |
530+
| **No micro-functions support** yet | Swagger UI is enabled on a per resolver instance which will limit its accuracy here. |
531+
| 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. |
532+
| 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. |
533533

534534
```python hl_lines="12-13" title="enabling_swagger.py"
535535
--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
835835

836836
These are native middlewares that may become native features depending on customer demand.
837837

838-
| Middleware | Purpose |
839-
| ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
838+
| Middleware | Purpose |
839+
| ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
840840
| [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"} |
841841

842842
#### Being a good citizen
@@ -1053,7 +1053,7 @@ When you're describing your API, declare security schemes at the top level, and
10531053
OpenAPI 3 lets you describe APIs protected using the following security schemes:
10541054

10551055
| Security Scheme | Type | Description |
1056-
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1056+
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
10571057
| [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"}) |
10581058
| [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"}. |
10591059
| [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 for: tests/functional/event_handler/test_api_gateway.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -291,12 +291,16 @@ def delete_func():
291291
def patch_func():
292292
raise RuntimeError()
293293

294+
@app.head("/no_matching_head")
295+
def head_func():
296+
raise RuntimeError()
297+
294298
def handler(event, context):
295299
return app.resolve(event, context)
296300

297301
# Also check the route configurations
298302
routes = app._static_routes
299-
assert len(routes) == 5
303+
assert len(routes) == 6
300304
for route in routes:
301305
if route.func == get_func:
302306
assert route.method == "GET"
@@ -308,6 +312,8 @@ def handler(event, context):
308312
assert route.method == "DELETE"
309313
elif route.func == patch_func:
310314
assert route.method == "PATCH"
315+
elif route.func == head_func:
316+
assert route.method == "HEAD"
311317

312318
# WHEN calling the handler
313319
# THEN return a 404

0 commit comments

Comments
 (0)