I instantiated the Cookiecutter SAM for Python Lambda functions, embedded the Lambda Powertools as a layer, then deployed it to my AWS account: all good!
Then I tried to configure Custom Domain Name for my API Gateway, and the API internal routing is no longer working.
Calling the API through the default execute-api endpoint ✅
curl https://{my-api-id}.execute-api.{region}.amazonaws.com/Prod/hello/pismy
Returns 200 OK:
{"message": "hello pismy"}
With CloudWatch logs:
{
"level": "INFO",
"location": "decorate:345",
"message": {
"resource": "/hello/{name}",
"path": "/hello/pismy",
"httpMethod": "GET",
...
"queryStringParameters": null,
"multiValueQueryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
"resourcePath": "/hello/{name}",
"httpMethod": "GET",
"path": "/Prod/hello/pismy",
"stage": "Prod",
"domainPrefix": "abcd1234",
"domainName": "abcd1234.execute-api.us-east-1.amazonaws.com",
"apiId": "abcd1234"
},
"body": null,
"isBase64Encoded": false
},
...
}
Calling the API through the Custom Domain Name 🟥
I first registered the API mapping with path hellopath
curl https://api.mydomain.xyz/hellopath/hello/pismy
Returns 404 Not Found:
{"statusCode":404,"message":"Not found"}
With CloudWatch logs:
{
"level": "INFO",
"location": "decorate:345",
"message": {
"resource": "/hello/{name}",
"path": "/hellopath/hello/pismy",
"httpMethod": "GET",
...
"queryStringParameters": null,
"multiValueQueryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
"resourcePath": "/hello/{name}",
"httpMethod": "GET",
"path": "/hellopath/hello/pismy",
"stage": "Prod",
"domainPrefix": "api",
"domainName": "api.mydomain.xyz",
"apiId": "abcd1234"
},
"body": null,
"isBase64Encoded": false
},
...
}
Possible Solution
As I'm seeing the log in Cloud Watch, that means the request reaches my Lambda, but it must be the internal routing to the handler function that fails.
@app.get("/hello/<name>")
def hello_you(name):
# query_strings_as_dict = app.current_event.query_string_parameters
# json_payload = app.current_event.json_body
return {"message": f"hello {name}"}
I guess Lambda Powertools must be using message.path or message.requestContext.path from the Lambda event rather than message.resource or message.requestContext.resource to implement the routing.
Unfortunately, when using Custom Domain Names, the message.path contains the API mapping prefix.
I instantiated the Cookiecutter SAM for Python Lambda functions, embedded the Lambda Powertools as a layer, then deployed it to my AWS account: all good!
Then I tried to configure Custom Domain Name for my API Gateway, and the API internal routing is no longer working.
Calling the API through the default
execute-apiendpoint ✅curl https://{my-api-id}.execute-api.{region}.amazonaws.com/Prod/hello/pismyReturns
200 OK:{"message": "hello pismy"}With CloudWatch logs:
{ "level": "INFO", "location": "decorate:345", "message": { "resource": "/hello/{name}", "path": "/hello/pismy", "httpMethod": "GET", ... "queryStringParameters": null, "multiValueQueryStringParameters": null, "pathParameters": null, "stageVariables": null, "requestContext": { "resourcePath": "/hello/{name}", "httpMethod": "GET", "path": "/Prod/hello/pismy", "stage": "Prod", "domainPrefix": "abcd1234", "domainName": "abcd1234.execute-api.us-east-1.amazonaws.com", "apiId": "abcd1234" }, "body": null, "isBase64Encoded": false }, ... }Calling the API through the Custom Domain Name 🟥
I first registered the API mapping with path
hellopathReturns
404 Not Found:{"statusCode":404,"message":"Not found"}With CloudWatch logs:
{ "level": "INFO", "location": "decorate:345", "message": { "resource": "/hello/{name}", "path": "/hellopath/hello/pismy", "httpMethod": "GET", ... "queryStringParameters": null, "multiValueQueryStringParameters": null, "pathParameters": null, "stageVariables": null, "requestContext": { "resourcePath": "/hello/{name}", "httpMethod": "GET", "path": "/hellopath/hello/pismy", "stage": "Prod", "domainPrefix": "api", "domainName": "api.mydomain.xyz", "apiId": "abcd1234" }, "body": null, "isBase64Encoded": false }, ... }Possible Solution
As I'm seeing the log in Cloud Watch, that means the request reaches my Lambda, but it must be the internal routing to the handler function that fails.
I guess Lambda Powertools must be using
message.pathormessage.requestContext.pathfrom the Lambda event rather thanmessage.resourceormessage.requestContext.resourceto implement the routing.Unfortunately, when using Custom Domain Names, the
message.pathcontains the API mapping prefix.