Skip to content

Commit 0f5c531

Browse files
authored
contrib/serverless/aws: normalize headers with v1 event format (#1982)
If the event has been generated from elb or api gateway and is in the v1 format normalize headers even if they already should per https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html Event discrimination logic courtesy of nodejs apm client. Fix #1980
1 parent 9bcc72d commit 0f5c531

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

elasticapm/contrib/serverless/aws.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,18 @@ def prep_kwargs(kwargs=None):
135135
return kwargs
136136

137137

138+
def should_normalize_headers(event: dict) -> bool:
139+
"""
140+
Helper to decide if we should normalize headers or not depending on the event
141+
142+
Even if the documentation says that headers are lowercased it's not always the case for format version 1.0
143+
https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
144+
"""
145+
146+
request_context = event.get("requestContext", {})
147+
return ("elb" in request_context or "requestId" in request_context) and "http" not in request_context
148+
149+
138150
class _lambda_transaction(object):
139151
"""
140152
Context manager for creating transactions around AWS Lambda functions.
@@ -162,7 +174,13 @@ def __enter__(self):
162174
# service like Step Functions, and is unlikely to be standardized
163175
# in any way. We just have to rely on our defaults in this case.
164176
self.event = {}
165-
trace_parent = TraceParent.from_headers(self.event.get("headers") or {})
177+
178+
headers = self.event.get("headers") or {}
179+
if headers and should_normalize_headers(self.event):
180+
normalized_headers = {k.lower(): v for k, v in headers.items()}
181+
else:
182+
normalized_headers = headers
183+
trace_parent = TraceParent.from_headers(normalized_headers)
166184

167185
global COLD_START
168186
cold_start = COLD_START

tests/contrib/serverless/aws_elb_test_data.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"connection": "Keep-Alive",
1616
"host": "blabla.com",
1717
"user-agent": "Apache-HttpClient/4.5.13 (Java/11.0.15)",
18+
"TraceParent": "00-12345678901234567890123456789012-1234567890123456-01",
1819
"x-amzn-trace-id": "Root=1-xxxxxxxxxxxxxx",
1920
"x-forwarded-for": "199.99.99.999",
2021
"x-forwarded-port": "443",

tests/contrib/serverless/aws_tests.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@
3636

3737
from elasticapm import capture_span
3838
from elasticapm.conf import constants
39-
from elasticapm.contrib.serverless.aws import capture_serverless, get_data_from_request, get_data_from_response
39+
from elasticapm.contrib.serverless.aws import (
40+
capture_serverless,
41+
get_data_from_request,
42+
get_data_from_response,
43+
should_normalize_headers,
44+
)
4045

4146

4247
@pytest.fixture
@@ -300,6 +305,7 @@ def test_func(event, context):
300305
assert transaction["context"]["request"]["headers"]
301306
assert transaction["context"]["response"]["status_code"] == 200
302307
assert transaction["context"]["service"]["origin"]["name"] == "lambda-279XGJDqGZ5rsrHC2Fjr"
308+
assert transaction["trace_id"] == "12345678901234567890123456789012"
303309

304310

305311
def test_capture_serverless_s3(event_s3, context, elasticapm_client):
@@ -477,3 +483,17 @@ def test_func(event, context):
477483

478484
test_func(event_api2, context)
479485
assert len(elasticapm_client.events[constants.TRANSACTION]) == 1
486+
487+
488+
def test_should_normalize_headers_true(event_api, event_elb):
489+
assert should_normalize_headers(event_api) is True
490+
assert should_normalize_headers(event_elb) is True
491+
492+
493+
def test_should_normalize_headers_false(event_api2, event_lurl, event_s3, event_s3_batch, event_sqs, event_sns):
494+
assert should_normalize_headers(event_api2) is False
495+
assert should_normalize_headers(event_lurl) is False
496+
assert should_normalize_headers(event_s3) is False
497+
assert should_normalize_headers(event_s3_batch) is False
498+
assert should_normalize_headers(event_sqs) is False
499+
assert should_normalize_headers(event_sns) is False

0 commit comments

Comments
 (0)