Skip to content

fix ResponseMetaDataTransformer #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions localstack_snapshot/snapshots/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,14 @@ def transform(self, input_data: dict, *, ctx: TransformContext) -> dict:
if k == "ResponseMetadata":
metadata = v
http_headers = metadata.get("HTTPHeaders")
if not isinstance(http_headers, dict):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good handling of non-expected values here 👏

continue

# TODO "x-amz-bucket-region"
# TestS3.test_region_header_exists -> verifies bucket-region

# FIXME: proper value is `content-type` with no underscore in lowercase, but this will necessitate a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a big problem actually. It's not the first time that we defer fixing issues in snapshot library because of backwards compatibility. Thanks for highlighting it! I added the issue about this to snapshots library backlog.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does yes. Maybe versioning could actually help here? Store the snapshot library version along the snapshot, to enjoy new features / support backward compatibility. Thanks for adding the issue on the backlog.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, versioning is the option I added to the backlog issue. It is not the straightforward one when projected onto test runs as we will need to run tests with different dependency versions, but definitely something to try.

# refresh of all snapshots
headers_to_collect = ["content_type"]
simplified_headers = {}
for h in headers_to_collect:
Expand Down
79 changes: 79 additions & 0 deletions tests/test_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from localstack_snapshot.snapshots.transformer import (
JsonStringTransformer,
ResponseMetaDataTransformer,
SortingTransformer,
TimestampTransformer,
TransformContext,
Expand Down Expand Up @@ -405,3 +406,81 @@ def test_generic_timestamp_transformer(self):
ctx = TransformContext()
output = transformer.transform(input, ctx=ctx)
assert output == expected


class TestResponseMetaDataTransformer:
def test_with_headers(self):
input_data = {"ResponseMetadata": {"HTTPHeaders": {"header1": "value1"}}}

metadata_transformer = ResponseMetaDataTransformer()

expected_key_value = {"ResponseMetadata": {"HTTPHeaders": {}}}

copied = copy.deepcopy(input_data)
ctx = TransformContext()
assert metadata_transformer.transform(copied, ctx=ctx) == expected_key_value
assert ctx.serialized_replacements == []

def test_with_headers_and_status_code(self):
input_data = {
"ResponseMetadata": {"HTTPHeaders": {"header1": "value1"}, "HTTPStatusCode": 500}
}

metadata_transformer = ResponseMetaDataTransformer()

expected_key_value = {"ResponseMetadata": {"HTTPHeaders": {}, "HTTPStatusCode": 500}}

copied = copy.deepcopy(input_data)
ctx = TransformContext()
assert metadata_transformer.transform(copied, ctx=ctx) == expected_key_value
assert ctx.serialized_replacements == []

def test_with_status_code_only(self):
input_data = {"ResponseMetadata": {"HTTPStatusCode": 500, "RandomData": "random"}}

metadata_transformer = ResponseMetaDataTransformer()

expected_key_value = {"ResponseMetadata": {"HTTPStatusCode": 500, "RandomData": "random"}}

copied = copy.deepcopy(input_data)
ctx = TransformContext()
assert metadata_transformer.transform(copied, ctx=ctx) == expected_key_value
assert ctx.serialized_replacements == []

def test_with_empty_response_metadata(self):
input_data = {"ResponseMetadata": {"NotHeaders": "data"}}

metadata_transformer = ResponseMetaDataTransformer()

expected_key_value = {"ResponseMetadata": {"NotHeaders": "data"}}

copied = copy.deepcopy(input_data)
ctx = TransformContext()
assert metadata_transformer.transform(copied, ctx=ctx) == expected_key_value
assert ctx.serialized_replacements == []

def test_with_headers_wrong_type(self):
input_data = {"ResponseMetadata": {"HTTPHeaders": "data"}}

metadata_transformer = ResponseMetaDataTransformer()

expected_key_value = {"ResponseMetadata": {"HTTPHeaders": "data"}}

copied = copy.deepcopy(input_data)
ctx = TransformContext()
assert metadata_transformer.transform(copied, ctx=ctx) == expected_key_value
assert ctx.serialized_replacements == []

def test_headers_filtering(self):
input_data = {
"ResponseMetadata": {"HTTPHeaders": {"content_type": "value1", "header1": "value1"}}
}

metadata_transformer = ResponseMetaDataTransformer()

expected_key_value = {"ResponseMetadata": {"HTTPHeaders": {"content_type": "value1"}}}

copied = copy.deepcopy(input_data)
ctx = TransformContext()
assert metadata_transformer.transform(copied, ctx=ctx) == expected_key_value
assert ctx.serialized_replacements == []