Skip to content

Commit b592fbd

Browse files
authored
Correct casing for x-amzn-RequestId header (#13230)
1 parent b54e78e commit b592fbd

File tree

5 files changed

+35
-21
lines changed

5 files changed

+35
-21
lines changed

localstack-core/localstack/aws/protocol/serializer.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,15 @@ def _prepare_additional_traits_in_xml(self, root: ETree.Element | None, request_
12281228
request_id_element = ETree.SubElement(response_metadata, "RequestId")
12291229
request_id_element.text = request_id
12301230

1231+
def _prepare_additional_traits_in_response(
1232+
self, response: Response, operation_model: OperationModel, request_id: str
1233+
):
1234+
response.headers["x-amzn-RequestId"] = request_id
1235+
response = super()._prepare_additional_traits_in_response(
1236+
response, operation_model, request_id
1237+
)
1238+
return response
1239+
12311240

12321241
class EC2ResponseSerializer(QueryResponseSerializer):
12331242
"""
@@ -1495,7 +1504,7 @@ def _serialize_type_blob(self, body: dict, value: str | bytes, _, key: str, mime
14951504
def _prepare_additional_traits_in_response(
14961505
self, response: Response, operation_model: OperationModel, request_id: str
14971506
):
1498-
response.headers["x-amzn-requestid"] = request_id
1507+
response.headers.setdefault("x-amzn-RequestId", request_id)
14991508
response = super()._prepare_additional_traits_in_response(
15001509
response, operation_model, request_id
15011510
)
@@ -1921,7 +1930,7 @@ def _serialize_body_params(
19211930
def _prepare_additional_traits_in_response(
19221931
self, response: Response, operation_model: OperationModel, request_id: str
19231932
) -> Response:
1924-
response.headers["x-amzn-requestid"] = request_id
1933+
response.headers["x-amzn-RequestId"] = request_id
19251934
response = super()._prepare_additional_traits_in_response(
19261935
response, operation_model, request_id
19271936
)
@@ -2015,7 +2024,7 @@ def _serialize_error(
20152024
def _prepare_additional_traits_in_response(
20162025
self, response: Response, operation_model: OperationModel, request_id: str
20172026
):
2018-
response.headers["x-amzn-requestid"] = request_id
2027+
response.headers["x-amzn-RequestId"] = request_id
20192028
response.headers["Smithy-Protocol"] = "rpc-v2-cbor"
20202029
response = super()._prepare_additional_traits_in_response(
20212030
response, operation_model, request_id

tests/aws/services/cloudwatch/test_cloudwatch.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2975,6 +2975,8 @@ def test_basic_operations_multiple_protocols(
29752975
payload=input_values,
29762976
)
29772977
assert response.status_code == 200
2978+
# Check if x-amzn-RequestId is in the response headers - case-sensitive check
2979+
assert "x-amzn-RequestId" in dict(response.headers)
29782980

29792981
get_metric_input = {
29802982
"MetricDataQueries": [

tests/aws/services/cloudwatch/test_cloudwatch.snapshot.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
}
4444
},
4545
"tests/aws/services/cloudwatch/test_cloudwatch.py::TestCloudWatchMultiProtocol::test_basic_operations_multiple_protocols[json]": {
46-
"recorded-date": "18-09-2025, 13:56:03",
46+
"recorded-date": "06-10-2025, 14:45:54",
4747
"recorded-content": {
4848
"describe-alarms": {
4949
"CompositeAlarms": [],
@@ -76,7 +76,7 @@
7676
}
7777
},
7878
"tests/aws/services/cloudwatch/test_cloudwatch.py::TestCloudWatchMultiProtocol::test_basic_operations_multiple_protocols[smithy-rpc-v2-cbor]": {
79-
"recorded-date": "18-09-2025, 13:56:06",
79+
"recorded-date": "06-10-2025, 14:45:56",
8080
"recorded-content": {
8181
"describe-alarms": {
8282
"CompositeAlarms": [],
@@ -109,7 +109,7 @@
109109
}
110110
},
111111
"tests/aws/services/cloudwatch/test_cloudwatch.py::TestCloudWatchMultiProtocol::test_basic_operations_multiple_protocols[query]": {
112-
"recorded-date": "18-09-2025, 13:56:09",
112+
"recorded-date": "06-10-2025, 14:45:59",
113113
"recorded-content": {
114114
"describe-alarms": {
115115
"DescribeAlarmsResponse": {

tests/aws/services/cloudwatch/test_cloudwatch.validation.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
{
22
"tests/aws/services/cloudwatch/test_cloudwatch.py::TestCloudWatchMultiProtocol::test_basic_operations_multiple_protocols[json]": {
3-
"last_validated_date": "2025-09-18T13:56:03+00:00",
3+
"last_validated_date": "2025-10-06T14:45:54+00:00",
44
"durations_in_seconds": {
5-
"setup": 0.48,
6-
"call": 3.45,
7-
"teardown": 0.0,
8-
"total": 3.93
5+
"setup": 0.82,
6+
"call": 2.64,
7+
"teardown": 0.01,
8+
"total": 3.47
99
}
1010
},
1111
"tests/aws/services/cloudwatch/test_cloudwatch.py::TestCloudWatchMultiProtocol::test_basic_operations_multiple_protocols[query]": {
12-
"last_validated_date": "2025-09-18T13:56:09+00:00",
12+
"last_validated_date": "2025-10-06T14:45:59+00:00",
1313
"durations_in_seconds": {
14-
"setup": 0.0,
15-
"call": 3.05,
16-
"teardown": 0.0,
17-
"total": 3.05
14+
"setup": 0.01,
15+
"call": 2.39,
16+
"teardown": 0.02,
17+
"total": 2.42
1818
}
1919
},
2020
"tests/aws/services/cloudwatch/test_cloudwatch.py::TestCloudWatchMultiProtocol::test_basic_operations_multiple_protocols[smithy-rpc-v2-cbor]": {
21-
"last_validated_date": "2025-09-18T13:56:06+00:00",
21+
"last_validated_date": "2025-10-06T14:45:56+00:00",
2222
"durations_in_seconds": {
2323
"setup": 0.0,
24-
"call": 3.05,
25-
"teardown": 0.0,
26-
"total": 3.05
24+
"call": 2.4,
25+
"teardown": 0.02,
26+
"total": 2.42
2727
}
2828
},
2929
"tests/aws/services/cloudwatch/test_cloudwatch.py::TestCloudWatchMultiProtocol::test_exception_serializing_with_no_shape_in_spec[json]": {

tests/unit/aws/protocol/test_serializer.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,11 @@ def _botocore_serializer_integration_test(
9797

9898
# Use the parser from botocore to parse the serialized response
9999
response_parser = create_parser(service_protocol)
100+
# Properly use HeadersDict from botocore to properly parse headers
101+
response_dict = serialized_response.to_readonly_response_dict()
102+
response_dict["headers"] = HeadersDict(response_dict.get("headers", {}))
100103
parsed_response = response_parser.parse(
101-
serialized_response.to_readonly_response_dict(),
104+
response_dict,
102105
service.operation_model(action).output_shape,
103106
)
104107

0 commit comments

Comments
 (0)