question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bug: APIGatewayRestResolver fails to route when "/" appears at end of route name

See original GitHub issue

Expected Behaviour

Given I am using APIGatewayRestResolver and I define a route as follows:

from aws_lambda_powertools.event_handler import APIGatewayRestResolver

app = APIGatewayRestResolver()

@app.get("/hello")
def hello_world():
    return {"message": "Hello World"}

I expect the following 2 GET request URLs:

  1. https://myapigwid.execute-api.ap-southeast-2.amazonaws.com/Prod/hello/
  2. https://myapigwid.execute-api.ap-southeast-2.amazonaws.com/Prod/hello

to return the same response:

{"message":"Hello World"}

Current Behaviour

Given I am using APIGatewayRestResolver and I define a route as follows:

@app.get("/hello")
def hello_world():
    return {"message": "Hello World"}

When I use the following URL:

  1. https://myapigwid.execute-api.ap-southeast-2.amazonaws.com/Prod/hello/

AWS Lambda Powertools returns a 404 not found response:

{"statusCode":404,"message":"Not found"}

Code snippet

from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools import Logger

app = APIGatewayRestResolver()
logger = Logger()

@app.get("/hello")
def hello_world():
    return {"message": "Hello World"}

@logger.inject_lambda_context(log_event=True)
def lambda_handler(event, context):
    logger.info("Executing app.resolve")
    return app.resolve(event, context)

Possible Solution

Route resolution uses the path attribute of the AWS API Gateway Lambda event so that the 2 URLs (one with trailing “/”) are no longer the same even though the API Gateway Service treats the routes correctly and executes the expected Lambda function.

I would suggest that during route resolution trailing “/” characters be removed and not considered in route resolution.

Unsure if this would be considered a breaking change and whether any customers are using this behaviour - I would not think this behaviour would be in use y customers but am unsure 😬

Steps to Reproduce

Create and deploy the SAM CLI Hello World function then replace the app.py with my code snippet above which has replaced it with AWS Lambda powertools resolver once deployed try loading the API in browser with and without trailing “/” character

AWS Lambda Powertools for Python version

latest

AWS Lambda function runtime

3.9

Packaging format used

PyPi

Debugging logs

START RequestId: a6a6f7b6-84db-4e1b-bfa6-59af38e9927d Version: $LATEST  2022/09/29/[$LATEST]c9ddb616b59546349b99ceaf1ef78e36

2022-09-29T17:49:38.102+10:00   {"level":"INFO","location":"decorate:352","message":{"resource":"/hello","path":"/hello","httpMethod":"GET",....} 2022/09/29/[$LATEST]c9ddb616b59546349b99ceaf1ef78e36

2022-09-29T17:49:38.102+10:00   {"level":"INFO","location":"lambda_handler:26","message":"Executing app.resolve","timestamp":"2022-09-29 07:49:38,102+0000","service":"service_undefined","cold_start":false,"function_name":"sam-app-HelloWorldFunction-nF3rtaBXzZ7S","function_memory_size":"128","function_arn":"arn:aws:lambda:ap-southeast-2:308836149415:function:sam-app-HelloWorldFunction-nF3rtaBXzZ7S","function_request_id":"a6a6f7b6-84db-4e1b-bfa6-59af38e9927d","xray_trace_id":"1-63354e12-521e23257116158e4057dc1e"}    2022/09/29/[$LATEST]c9ddb616b59546349b99ceaf1ef78e36

2022-09-29T17:49:38.103+10:00   END RequestId: a6a6f7b6-84db-4e1b-bfa6-59af38e9927d 2022/09/29/[$LATEST]c9ddb616b59546349b99ceaf1ef78e36

2022-09-29T17:49:38.103+10:00   REPORT RequestId: a6a6f7b6-84db-4e1b-bfa6-59af38e9927d Duration: 1.88 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used: 57 MB   2022/09/29/[$LATEST]c9ddb616b59546349b99ceaf1ef78e36

2022-09-29T17:49:41.754+10:00   START RequestId: e119c41b-45a7-464b-8931-cde0f6b2b51e Version: $LATEST  2022/09/29/[$LATEST]c9ddb616b59546349b99ceaf1ef78e36

2022-09-29T17:49:41.755+10:00   {"level":"INFO","location":"decorate:352","message":{"resource":"/hello","path":"/hello/","httpMethod":"GET",....} 2022/09/29/[$LATEST]c9ddb616b59546349b99ceaf1ef78e36

2022-09-29T17:49:41.755+10:00   {"level":"INFO","location":"lambda_handler:26","message":"Executing app.resolve","timestamp":"2022-09-29 07:49:41,755+0000","service":"service_undefined","cold_start":false,"function_name":"sam-app-HelloWorldFunction-nF3rtaBXzZ7S","function_memory_size":"128","function_arn":"arn:aws:lambda:ap-southeast-2:308836149415:function:sam-app-HelloWorldFunction-nF3rtaBXzZ7S","function_request_id":"e119c41b-45a7-464b-8931-cde0f6b2b51e","xray_trace_id":"1-63354e15-4cad301429daa2311eaa530a"}    2022/09/29/[$LATEST]c9ddb616b59546349b99ceaf1ef78e36

2022-09-29T17:49:41.756+10:00   END RequestId: e119c41b-45a7-464b-8931-cde0f6b2b51e 2022/09/29/[$LATEST]c9ddb616b59546349b99ceaf1ef78e36

2022-09-29T17:49:41.756+10:00   REPORT RequestId: e119c41b-45a7-464b-8931-cde0f6b2b51e Duration: 1.68 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
heitorlessacommented, Sep 30, 2022

Apologies for the delay, handling a sensitive issue in the last 24 hours. Back now.

RestAPI (v1) route both "/hello/" and "/hello to the same Lambda, so it does HTTP API.

This is surprising. I vividly remember REST API failing with authorization token when the route had a trailing slash.

about consistency

I agree with you, we should match the experience on API Gateway. We should also have an E2E test to be sure this won’t bite us in the future. It could be easier to test with ALB too via E2E as we already have one.

Feel free to shout if you need any help with the E2E test. It should be easy to add a new function, but the details are here if you ever need: https://github.com/awslabs/aws-lambda-powertools-python/blob/develop/MAINTAINERS.md#run-end-to-end-tests

Thanks a lot for digging on this!

1reaction
walmslescommented, Sep 29, 2022

hmmm … In my test project Lambda was executed for both trailing slash and not trailing slash.

Let me clarify the behaviour - its been working this way from memory for a while now

Will look at testing across the various resolvers as well. Let me confirm the behaviours everywhere and come back - happy to put a pull-request together for this one.

Read more comments on GitHub >

github_iconTop Results From Across the Web

AWS API Gateway: Error when renaming path variable #3785
Expected the service to deploy the new route over the old one. Renaming the path variable from pathvar to pathVar . What stacktrace...
Read more >
Tutorial - AWS Lambda Powertools for Python
Let's expand our application with a new route - /hello/{name} . ... if/else to handle several routes & HTTP Methods can be error...
Read more >
AWS API Gateway : route error - Stack Overflow
I had the same problem and solved it. The problem is in the Invoke URL you're using. To fix this, please correct path:...
Read more >
Resolve API Gateway REST API Lambda integration errors
When I invoke my AWS Lambda function using an Amazon API Gateway REST API, I get an "Invalid permissions on Lambda function" error....
Read more >
Develop Lambda functions with AWS Lambda Powertools
... flushed upon request completion/failure def lambda_handler(event: dict, ... Logger() app = APIGatewayRestResolver() # API route resolver ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found