Thinking about using an AWS Lambda function using the excellent awslabs/aws-serverless-java-container as an AWS Application Load Balancer (ALB) target? There are some configuration gotchas you should know about!
ALB Lambda Target Configuration
When you set up an ALB target group, you can configure the group using Target Group Attributes. For Lambda functions, the attribute lambda.multi_value_headers.enabled
is set to false
by default. This causes the ALB to send proxy web requests to the Lambda using single-value query parameter and header mappings:
{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/prod-example-function/e77803ebb6d2c24"
}
},
"httpMethod": "PUT",
"path": "/path/to/resource",
"queryStringParameters": {},
"headers": {
"accept": "*",
"content-length": "17",
"content-type": "application/json",
"host": "stackoverflow.name",
"user-agent": "curl/7.77.0",
"x-amzn-trace-id": "Root=1-62e22402-3a5f246225e45edd7735c182",
"x-forwarded-for": "24.14.13.186",
"x-forwarded-port": "443",
"x-forwarded-proto": "https",
"x-jersey-tracing-accept": "true"
},
"body": "{\"alpha\":\"bravo\"}",
"isBase64Encoded": false
}
The Problem
As of the time of this writing, the awslabs/aws-serverless-java-container library does not parse those single-value maps properly. This means the Lambda function doesn’t receive request headers or query parameters, which causes a variety of issues. In my case, the problem was POST
and PUT
requests resulting in a HTTP 415 Unsupported Media Type
response even though those endpoints worked in another container.
The Solution
Fortunately, the solution is simple: just set lambda.multi_value_headers.enabled
to true
. This causes the ALB to send multi-value maps instead:
{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/prod-example-function/e77803ebb6d2c24"
}
},
"httpMethod": "PUT",
"path": "/path/to/resource",
"multiValueQueryStringParameters": {},
"multiValueHeaders": {
"accept": [
"*"
],
"content-length": [
"17"
],
"content-type": [
"application/json"
],
"host": [
"stackoverflow.name"
],
"user-agent": [
"curl/7.77.0"
],
"x-amzn-trace-id": [
"Root=1-62e22402-3a5f246225e45edd7735c182"
],
"x-forwarded-for": [
"24.14.13.186"
],
"x-forwarded-port": [
"443"
],
"x-forwarded-proto": [
"https"
],
"x-jersey-tracing-accept": [
"true"
]
},
"body": "{\"alpha\":\"bravo\"}",
"isBase64Encoded": false
}
The awslabs/aws-serverless-java-container library parses these values happily.
The Fix
I’ve proposed a fix to the code that would handle the single-valued maps properly and an update to the docs that would call out this configuration change more clearly. I’ll update here if and when those PRs get merged!