Skip to content

Feature request: Add Event handler for AWS Lambda Function URLs #1142

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

Closed
2 tasks done
gwlester opened this issue Apr 21, 2022 · 12 comments
Closed
2 tasks done

Feature request: Add Event handler for AWS Lambda Function URLs #1142

gwlester opened this issue Apr 21, 2022 · 12 comments
Assignees
Labels
feature-request feature request

Comments

@gwlester
Copy link
Contributor

Use case

With the general availability of AWS Lambda Function URLs to implement microservices AWS Lambda Powertools for Python should support handling this event type.

This should support the routes being specified in a separate file just like for other event handlers.

Solution/User Experience

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.event_handler import FunctionUrl

tracer = Tracer()
logger = Logger()
app = FunctionUrl()

@app.get("/hello")
@tracer.capture_method
def get_hello_universe():
    return {"message": "hello universe"}

# You can continue to use other utilities just as before
@logger.inject_lambda_context(correlation_id_path=correlation_paths.FUNCTION_URL)
@tracer.capture_lambda_handler
def lambda_handler(event, context):
    return app.resolve(event, context)

Alternative solutions

No response

Acknowledgment

@gwlester gwlester added feature-request feature request triage Pending triage from maintainers labels Apr 21, 2022
@gwlester
Copy link
Contributor Author

It would be nice if when specifying the route an optional "authorizer function" could be passed. Such a function would have the same signature as a handler and whose result could be a boolean indicating if access is allowed or not. If no "authorizer function" then all access would be allowed for that route.

@heitorlessa heitorlessa added the revisit-in-3-months Requires more customers feedback before making or revisiting a decision label Apr 21, 2022
@heitorlessa
Copy link
Contributor

Thank you @gwlester for showing interest in having support for Lambda Function URL. We'll look into it after we return from our pause.

We built support during beta, so it should be technically a days job to revisit and consider maintenance aspects.

As for authorisers, we'd prefer to create a middleware support for event handler (in-flight, after the pause) so that we don't recommend non-function URL customers to disregard API GW/ALB/AppSync Authorizer capabilities.

Thank you!

@heitorlessa heitorlessa removed the triage Pending triage from maintainers label Apr 21, 2022
@michaelbrewer
Copy link
Contributor

@gwlester this already works via the http api handler

@michaelbrewer
Copy link
Contributor

This code works fine

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.event_handler import APIGatewayHttpResolver

tracer = Tracer()
logger = Logger()
app = APIGatewayHttpResolver()

@app.get("/hello")
@tracer.capture_method
def get_hello_universe():
    return {"message": "hello universe"}

# You can continue to use other utilities just as before
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
@tracer.capture_lambda_handler
def lambda_handler(event, context):
    return app.resolve(event, context)

Also the sample projects works ok too:

from aws_lambda_powertools import Logger, Metrics, Tracer
from aws_lambda_powertools.event_handler.api_gateway import APIGatewayHttpResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.metrics import MetricUnit

logger = Logger(service="APP")
tracer = Tracer(service="APP")
metrics = Metrics(namespace="MyApp", service="APP")
app = APIGatewayHttpResolver()


@app.get("/hello/<name>")
@tracer.capture_method
def hello_name(name):
    tracer.put_annotation(key="User", value=name)
    logger.info(f"Request from {name} received")
    metrics.add_metric(name="SuccessfulGreetings", unit=MetricUnit.Count, value=1)
    return {"message": f"hello {name}!"}


@app.get("/hello")
@tracer.capture_method
def hello():
    tracer.put_annotation(key="User", value="unknown")
    logger.info("Request from unknown received")
    metrics.add_metric(name="SuccessfulGreetings", unit=MetricUnit.Count, value=1)
    return {"message": "hello unknown!"}


@tracer.capture_lambda_handler
@logger.inject_lambda_context(
    correlation_id_path=correlation_paths.API_GATEWAY_HTTP, log_event=True
)
@metrics.log_metrics(capture_cold_start_metric=True)
def lambda_handler(event, context):
    try:
        return app.resolve(event, context)
    except Exception as e:
        logger.exception(e)
        raise
{
    "level": "INFO",
    "location": "decorate:352",
    "message": {
        "version": "2.0",
        "routeKey": "$default",
        "rawPath": "/hello/foo",
        "rawQueryString": "",
        "headers": {
            "sec-fetch-mode": "navigate",
            "sec-fetch-site": "none",
            "accept-language": "en-US,en;q=0.9",
            "x-forwarded-proto": "https",
            "x-forwarded-port": "443",
            "x-forwarded-for": "24.25.211.231",
            "sec-fetch-user": "?1",
            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
            "sec-gpc": "1",
            "x-amzn-trace-id": "Root=1-6260fcf5-4cf3d34a732581c86e1a7e0e",
            "host": "bg6wooanpk5l6pte7d73k2flmy0pmkms.lambda-url.us-east-2.on.aws",
            "upgrade-insecure-requests": "1",
            "cache-control": "max-age=0",
            "accept-encoding": "gzip, deflate, br",
            "sec-fetch-dest": "document",
            "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
        },
        "requestContext": {
            "accountId": "anonymous",
            "apiId": "bg6wooanpk5l6pte7d73k2flmy0pmkms",
            "domainName": "bg6wooanpk5l6pte7d73k2flmy0pmkms.lambda-url.us-east-2.on.aws",
            "domainPrefix": "bg6wooanpk5l6pte7d73k2flmy0pmkms",
            "http": {
                "method": "GET",
                "path": "/hello/foo",
                "protocol": "HTTP/1.1",
                "sourceIp": "24.25.211.231",
                "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
            },
            "requestId": "ed9f2d37-4585-479b-98c0-3dea09aaecaf",
            "routeKey": "$default",
            "stage": "$default",
            "time": "21/Apr/2022:06:43:01 +0000",
            "timeEpoch": 1650523381869
        },
        "isBase64Encoded": false
    },
    "timestamp": "2022-04-21 06:43:01,874+0000",
    "service": "APP",
    "sampling_rate": "0.1",
    "cold_start": false,
    "function_name": "sam-app-HelloWorldFunction-jNNQamivEruW",
    "function_memory_size": "256",
    "function_arn": "arn:aws:lambda:us-east-2:254688924456:function:sam-app-HelloWorldFunction-jNNQamivEruW",
    "function_request_id": "ed9f2d37-4585-479b-98c0-3dea09aaecaf",
    "correlation_id": "ed9f2d37-4585-479b-98c0-3dea09aaecaf",
    "xray_trace_id": "1-6260fcf5-4cf3d34a732581c86e1a7e0e"
}

Screen Shot 2022-04-20 at 11 42 02 PM

@gwlester
Copy link
Contributor Author

@michaelbrewer -- after looking at the code last night it looked like it would "just work". It would still be nice to have an explicit class for it.

I know ya'll did some work on this already -- would you mind/like if I took a crack and submitted a Pull Request with it (assuming that I have time before August)?

@michaelbrewer
Copy link
Contributor

Go for it. But to save you time and frustration, I would suggest waiting for an official green light from the maintainers, otherwise your PR will most likely be closed.

Also for Function Url we should probably have some disclaimers and warnings around security.

@gwlester
Copy link
Contributor Author

Ok, I will just wait for a status change on this or to hear back from ya'll.

@heitorlessa heitorlessa removed the revisit-in-3-months Requires more customers feedback before making or revisiting a decision label Jun 13, 2022
@heitorlessa
Copy link
Contributor

Hey @gwlester we'll be looking in implementing official support for Lambda Function URL as soon as our pause ends.

@rubenfonseca
Copy link
Contributor

Hi @gwlester! We're looking to start implementing this feature for release at the end of the next week. We would love if you had the change to contribute the necessary changes yourself. Otherwise, we will also be happy to take a look and ask you for a review. What would be the best for you?

@rubenfonseca
Copy link
Contributor

Hi @gwlester we've now worked on an implementation of the AWS Lambda Function URL data class and event handler here: #1408

We would appreciate if you take a look and review the code. And we're looking forward to any feedback you might have.

@gwlester
Copy link
Contributor Author

gwlester commented Aug 3, 2022 via email

@github-actions github-actions bot added the pending-release Fix or implementation already in dev waiting to be released label Aug 4, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Aug 5, 2022

This is now released under 1.27.0 version!

@github-actions github-actions bot closed this as completed Aug 5, 2022
@github-actions github-actions bot removed the pending-release Fix or implementation already in dev waiting to be released label Aug 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request feature request
Projects
None yet
Development

No branches or pull requests

4 participants