-
Notifications
You must be signed in to change notification settings - Fork 421
feat(event_handlers): Add support for Lambda Function URLs #1408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
heitorlessa
merged 10 commits into
aws-powertools:develop
from
rubenfonseca:feat/lambda-function-urls
Aug 4, 2022
Merged
Changes from 7 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
a8b3f48
feat(event_sources): add support for Lambda Function URL events
rubenfonseca aca525c
feat(event_handlers): add support for Lambda Function URL
rubenfonseca cb3bc5b
chore(docs): add documentation for Lambda Functoin URLs
rubenfonseca 1039c04
chore(docs): remove file commited by mistake
rubenfonseca febe483
chore(docs): updated links
rubenfonseca 184d84f
chore(docs): typo
rubenfonseca 0711e6d
chore: typos
rubenfonseca a47f6eb
chore(event_handlers): apply suggestions from code review
rubenfonseca 8ccf4b6
chore(tests): add missing new line
rubenfonseca eaebeee
chore(tests): typo
rubenfonseca File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
aws_lambda_powertools/event_handler/lambda_function_url.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
from typing import Callable, Dict, List, Optional | ||
|
||
from aws_lambda_powertools.event_handler import CORSConfig | ||
from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver, ProxyEventType | ||
from aws_lambda_powertools.utilities.data_classes import LambdaFunctionUrlEvent | ||
|
||
|
||
class LambdaFunctionUrlResolver(ApiGatewayResolver): | ||
"""AWS Lambda Function URL resolver | ||
|
||
Notes: | ||
----- | ||
For now, this seems to work the same way as API Gateway HTTP APIs Payload Format Version 2.0. | ||
rubenfonseca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Documentation: | ||
- https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html | ||
- https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-payloads | ||
|
||
Examples | ||
-------- | ||
Simple example with a custom lambda handler using the Tracer capture_lambda_handler decorator | ||
rubenfonseca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```python | ||
from aws_lambda_powertools import Tracer | ||
from aws_lambda_powertools.event_handler import LambdaFunctionUrlResolver | ||
|
||
tracer = Tracer() | ||
app = LambdaFunctionUrlResolver() | ||
|
||
@app.get("/get-call") | ||
def simple_get(): | ||
return {"message": "Foo"} | ||
|
||
@app.post("/post-call") | ||
def simple_post(): | ||
post_data: dict = app.current_event.json_body | ||
return {"message": post_data["value"]} | ||
rubenfonseca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
@tracer.capture_lambda_handler | ||
def lambda_handler(event, context): | ||
return app.resolve(event, context) | ||
""" | ||
|
||
current_event: LambdaFunctionUrlEvent | ||
|
||
def __init__( | ||
self, | ||
cors: Optional[CORSConfig] = None, | ||
debug: Optional[bool] = None, | ||
serializer: Optional[Callable[[Dict], str]] = None, | ||
strip_prefixes: Optional[List[str]] = None, | ||
): | ||
super().__init__(ProxyEventType.LambdaFunctionUrlEvent, cors, debug, serializer, strip_prefixes) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
aws_lambda_powertools/utilities/data_classes/lambda_function_url_event.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from aws_lambda_powertools.utilities.data_classes.api_gateway_proxy_event import APIGatewayProxyEventV2 | ||
|
||
|
||
class LambdaFunctionUrlEvent(APIGatewayProxyEventV2): | ||
"""AWS Lambda Function URL event | ||
|
||
Notes: | ||
----- | ||
For now, this seems to follow the exact same payload as HTTP APIs Payload Format Version 2.0. | ||
Certain keys in this payload format don't make sense for function urls (e.g: `routeKey`, `stage`). | ||
These keys will have default values that come on the payload, but they are not useful since they can't be changed. | ||
rubenfonseca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Documentation: | ||
- https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html | ||
- https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-payloads | ||
""" | ||
|
||
pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,11 +3,11 @@ title: REST API | |
description: Core utility | ||
--- | ||
|
||
Event handler for Amazon API Gateway REST and HTTP APIs, and Application Loader Balancer (ALB). | ||
Event handler for Amazon API Gateway REST and HTTP APIs, Application Loader Balancer (ALB), and Lambda Function URLs. | ||
|
||
## Key Features | ||
|
||
* Lightweight routing to reduce boilerplate for API Gateway REST/HTTP API and ALB | ||
* Lightweight routing to reduce boilerplate for API Gateway REST/HTTP API, ALB and Lambda Function URLs. | ||
* Support for CORS, binary and Gzip compression, Decimals JSON encoding and bring your own JSON serializer | ||
* Built-in integration with [Event Source Data Classes utilities](../../utilities/data_classes.md){target="_blank"} for self-documented event schema | ||
|
||
|
@@ -18,23 +18,31 @@ Event handler for Amazon API Gateway REST and HTTP APIs, and Application Loader | |
|
||
### Required resources | ||
|
||
You must have an existing [API Gateway Proxy integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html){target="_blank"} or [ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html){target="_blank"} configured to invoke your Lambda function. | ||
If you're using any API Gateway integration, you must have an existing [API Gateway Proxy integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html){target="_blank"} or [ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html){target="_blank"} configured to invoke your Lambda function. | ||
|
||
This is the sample infrastructure for API Gateway we are using for the examples in this documentation. | ||
This is the sample infrastructure for API Gateway and Lambda Function URLs we are using for the examples in this documentation. | ||
|
||
???+ info "There is no additional permissions or dependencies required to use this utility." | ||
|
||
```yaml title="AWS Serverless Application Model (SAM) example" | ||
--8<-- "examples/event_handler_rest/sam/template.yaml" | ||
``` | ||
=== "API Gateway SAM Template" | ||
|
||
```yaml title="AWS Serverless Application Model (SAM) example" | ||
--8<-- "examples/event_handler_rest/sam/template.yaml" | ||
``` | ||
|
||
=== "Lambda Function URL SAM Template" | ||
|
||
```yaml title="AWS Serverless Application Model (SAM) example" | ||
--8<-- "examples/event_handler_lambda_function_url/sam/template.yaml" | ||
``` | ||
|
||
### Event Resolvers | ||
|
||
Before you decorate your functions to handle a given path and HTTP method(s), you need to initialize a resolver. | ||
|
||
A resolver will handle request resolution, including [one or more routers](#split-routes-with-router), and give you access to the current event via typed properties. | ||
|
||
For resolvers, we provide: `APIGatewayRestResolver`, `APIGatewayHttpResolver`, and `ALBResolver`. | ||
For resolvers, we provide: `APIGatewayRestResolver`, `APIGatewayHttpResolver`, `ALBResolver`, and `LambdaFunctionUrlResolver` . | ||
|
||
???+ info | ||
We will use `APIGatewayRestResolver` as the default across examples. | ||
|
@@ -87,6 +95,22 @@ When using Amazon Application Load Balancer (ALB) to front your Lambda functions | |
--8<-- "examples/event_handler_rest/src/getting_started_alb_api_resolver.py" | ||
``` | ||
|
||
#### Lambda Function URL | ||
|
||
When using an [AWS Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html), you can use `LambdaFunctionUrlResolver`. | ||
rubenfonseca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
=== "getting_started_lambda_function_url_resolver.py" | ||
|
||
```python hl_lines="5 11" title="Using Lambda Function URL resolver" | ||
--8<-- "examples/event_handler_lambda_function_url/src/getting_started_lambda_function_url_resolver.py" | ||
``` | ||
|
||
=== "getting_started_lambda_function_url_resolver.json" | ||
|
||
```json hl_lines="4-5" title="Example payload delivered to the handler" | ||
--8<-- "examples/event_handler_lambda_function_url/src/getting_started_lambda_function_url_resolver.json" | ||
``` | ||
|
||
### Dynamic routes | ||
|
||
You can use `/todos/<todo_id>` to configure dynamic URL paths, where `<todo_id>` will be resolved at runtime. | ||
|
@@ -270,7 +294,7 @@ This will ensure that CORS headers are always returned as part of the response w | |
|
||
#### Pre-flight | ||
|
||
Pre-flight (OPTIONS) calls are typically handled at the API Gateway level as per [our sample infrastructure](#required-resources), no Lambda integration necessary. However, ALB expects you to handle pre-flight requests. | ||
Pre-flight (OPTIONS) calls are typically handled at the API Gateway or Lambda Function URL level as per [our sample infrastructure](#required-resources), no Lambda integration necessary. However, ALB expects you to handle pre-flight requests. | ||
rubenfonseca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
For convenience, we automatically handle that for you as long as you [setup CORS in the constructor level](#cors). | ||
|
||
|
@@ -338,6 +362,7 @@ Like `compress` feature, the client must send the `Accept` header with the corre | |
|
||
???+ warning | ||
This feature requires API Gateway to configure binary media types, see [our sample infrastructure](#required-resources) for reference. | ||
For Lambda Function URLs, no additional configuration is necessary. | ||
|
||
rubenfonseca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
=== "binary_responses.py" | ||
|
||
|
@@ -380,7 +405,7 @@ This will enable full tracebacks errors in the response, print request and respo | |
|
||
### Custom serializer | ||
|
||
You can instruct API Gateway handler to use a custom serializer to best suit your needs, for example take into account Enums when serializing. | ||
You can instruct an event handler to use a custom serializer to best suit your needs, for example take into account Enums when serializing. | ||
rubenfonseca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```python hl_lines="35 40" title="Using a custom JSON serializer for responses" | ||
--8<-- "examples/event_handler_rest/src/custom_serializer.py" | ||
|
@@ -501,7 +526,7 @@ A micro function means that your final code artifact will be different to each f | |
|
||
**Downsides** | ||
|
||
* **Upfront investment**. You need custom build tooling to bundle assets, including [C bindings for runtime compatibility](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html){target="_blank"}. `Operations become more elaborate — you need to standardize tracing labels/annotations, structured logging, and metrics to pinpoint root causes. | ||
* **Upfront investment**. You need custom build tooling to bundle assets, including [C bindings for runtime compatibility](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html){target="_blank"}. Operations become more elaborate — you need to standardize tracing labels/annotations, structured logging, and metrics to pinpoint root causes. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. great catch!! |
||
* Engineering discipline is necessary for both approaches. Micro-function approach however requires further attention in consistency as the number of functions grow, just like any distributed system. | ||
* **Harder to share code**. Shared code must be carefully evaluated to avoid unnecessary deployments when that changes. Equally, if shared code isn't a library, | ||
your development, building, deployment tooling need to accommodate the distinct layout. | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note to future self: we should improve the return type to a more accurate one with
@overload
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note to future self: wait for python 3.10 to actually have proper pattern matching