From 7c8ee70d08c6cb231bff0643e4c646a8910578e0 Mon Sep 17 00:00:00 2001 From: SamRemis Date: Fri, 17 Oct 2025 13:55:40 -0400 Subject: [PATCH 01/11] Update CRT HTTP client to include the port in the host for the CRT client if it adds the header --- packages/smithy-http/src/smithy_http/aio/crt.py | 2 +- packages/smithy-http/tests/unit/aio/test_crt.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/smithy-http/src/smithy_http/aio/crt.py b/packages/smithy-http/src/smithy_http/aio/crt.py index 4dd3232b..a450ef9c 100644 --- a/packages/smithy-http/src/smithy_http/aio/crt.py +++ b/packages/smithy-http/src/smithy_http/aio/crt.py @@ -273,7 +273,7 @@ def _marshal_request( headers_list: list[tuple[str, str]] = [] if "host" not in request.fields: request.fields.set_field( - Field(name="host", values=[request.destination.host]) + Field(name="host", values=[request.destination.netloc]) ) if "accept" not in request.fields: diff --git a/packages/smithy-http/tests/unit/aio/test_crt.py b/packages/smithy-http/tests/unit/aio/test_crt.py index 5b9e851e..bed5fd38 100644 --- a/packages/smithy-http/tests/unit/aio/test_crt.py +++ b/packages/smithy-http/tests/unit/aio/test_crt.py @@ -44,6 +44,19 @@ def test_client_marshal_request() -> None: assert crt_request.method == "GET" assert crt_request.path == "/path?key1=value1&key2=value2" +async def test_port_included_in_host_header() -> None: + client = AWSCRTHTTPClient() + request = HTTPRequest( + method="GET", + destination=URI( + host="example.com", path="/path", query="key1=value1&key2=value2", port=8443 + ), + body=BytesIO(), + fields=Fields(), + ) + crt_request, _ = await client._marshal_request(request) # type: ignore + assert crt_request.headers.get("host") == "example.com:8443" # type: ignore + async def test_body_generator_bytes() -> None: """Test body generator with bytes input.""" From dd2937aeba9d0a39354cbbd18e82dac220136d33 Mon Sep 17 00:00:00 2001 From: SamRemis Date: Fri, 17 Oct 2025 15:33:41 -0400 Subject: [PATCH 02/11] Add new fields added by signed_fields to the request --- packages/aws-sdk-signers/src/aws_sdk_signers/signers.py | 8 ++++++++ packages/aws-sdk-signers/tests/unit/test_signers.py | 2 ++ 2 files changed, 10 insertions(+) diff --git a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py index 29ba0289..84e37726 100644 --- a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py +++ b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py @@ -99,6 +99,10 @@ def sign( ) signing_fields = self._normalize_signing_fields(request=new_request) + #If any headers have been added, make sure those are reflected in the new request + for field_name, field_value in signing_fields.items(): + if field_name not in request.fields: + new_request.fields.set_field(Field(name=field_name, values=[field_value])) credential_scope = self._scope(signing_properties=new_signing_properties) credential = f"{identity.access_key_id}/{credential_scope}" authorization = self.generate_authorization_field( @@ -476,6 +480,10 @@ async def sign( ) signing_fields = await self._normalize_signing_fields(request=new_request) + #If any headers have been added, make sure those are reflected in the new request + for field_name, field_value in signing_fields.items(): + if field_name not in request.fields: + new_request.fields.set_field(Field(name=field_name, values=[field_value])) credential_scope = await self._scope(signing_properties=new_signing_properties) credential = f"{identity.access_key_id}/{credential_scope}" authorization = await self.generate_authorization_field( diff --git a/packages/aws-sdk-signers/tests/unit/test_signers.py b/packages/aws-sdk-signers/tests/unit/test_signers.py index cafef288..7c52a936 100644 --- a/packages/aws-sdk-signers/tests/unit/test_signers.py +++ b/packages/aws-sdk-signers/tests/unit/test_signers.py @@ -94,6 +94,8 @@ def test_sign_doesnt_modify_original_request( assert signed_request is not aws_request assert aws_request.fields == original_request.fields assert signed_request.fields != aws_request.fields + assert 'host' in signed_request.fields + assert 'authorization' in signed_request.fields @typing.no_type_check def test_sign_with_invalid_identity( From 674a73a06a970b2b36eacdb3eb49c1fd77df0f17 Mon Sep 17 00:00:00 2001 From: SamRemis Date: Fri, 17 Oct 2025 15:58:24 -0400 Subject: [PATCH 03/11] linter --- .../aws-sdk-signers/src/aws_sdk_signers/signers.py | 12 ++++++++---- packages/aws-sdk-signers/tests/unit/test_signers.py | 4 ++-- packages/smithy-http/tests/unit/aio/test_crt.py | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py index 84e37726..015d27bf 100644 --- a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py +++ b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py @@ -99,10 +99,12 @@ def sign( ) signing_fields = self._normalize_signing_fields(request=new_request) - #If any headers have been added, make sure those are reflected in the new request + # If any headers have been added, make sure those are reflected in the new request for field_name, field_value in signing_fields.items(): if field_name not in request.fields: - new_request.fields.set_field(Field(name=field_name, values=[field_value])) + new_request.fields.set_field( + Field(name=field_name, values=[field_value]) + ) credential_scope = self._scope(signing_properties=new_signing_properties) credential = f"{identity.access_key_id}/{credential_scope}" authorization = self.generate_authorization_field( @@ -480,10 +482,12 @@ async def sign( ) signing_fields = await self._normalize_signing_fields(request=new_request) - #If any headers have been added, make sure those are reflected in the new request + # If any headers have been added, make sure those are reflected in the new request for field_name, field_value in signing_fields.items(): if field_name not in request.fields: - new_request.fields.set_field(Field(name=field_name, values=[field_value])) + new_request.fields.set_field( + Field(name=field_name, values=[field_value]) + ) credential_scope = await self._scope(signing_properties=new_signing_properties) credential = f"{identity.access_key_id}/{credential_scope}" authorization = await self.generate_authorization_field( diff --git a/packages/aws-sdk-signers/tests/unit/test_signers.py b/packages/aws-sdk-signers/tests/unit/test_signers.py index 7c52a936..f71b11de 100644 --- a/packages/aws-sdk-signers/tests/unit/test_signers.py +++ b/packages/aws-sdk-signers/tests/unit/test_signers.py @@ -94,8 +94,8 @@ def test_sign_doesnt_modify_original_request( assert signed_request is not aws_request assert aws_request.fields == original_request.fields assert signed_request.fields != aws_request.fields - assert 'host' in signed_request.fields - assert 'authorization' in signed_request.fields + assert "host" in signed_request.fields + assert "authorization" in signed_request.fields @typing.no_type_check def test_sign_with_invalid_identity( diff --git a/packages/smithy-http/tests/unit/aio/test_crt.py b/packages/smithy-http/tests/unit/aio/test_crt.py index bed5fd38..89eacbce 100644 --- a/packages/smithy-http/tests/unit/aio/test_crt.py +++ b/packages/smithy-http/tests/unit/aio/test_crt.py @@ -44,6 +44,7 @@ def test_client_marshal_request() -> None: assert crt_request.method == "GET" assert crt_request.path == "/path?key1=value1&key2=value2" + async def test_port_included_in_host_header() -> None: client = AWSCRTHTTPClient() request = HTTPRequest( From 078aaf23cee27726ca6d791086e5c41c98f34bdf Mon Sep 17 00:00:00 2001 From: SamRemis Date: Fri, 17 Oct 2025 16:53:58 -0400 Subject: [PATCH 04/11] Implement feedback --- .../src/aws_sdk_signers/signers.py | 25 +++++++++++-------- .../smithy-http/src/smithy_http/aio/crt.py | 7 +++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py index 015d27bf..859e6433 100644 --- a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py +++ b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py @@ -218,6 +218,9 @@ def _apply_required_fields( request.fields.set_field( Field(name="X-Amz-Security-Token", values=[identity.session_token]) ) + if "host" not in request.fields: + host = self._normalize_host_field(uri=request.destination) + request.fields.set_field(Field(name="host", values=[host])) def canonical_request( self, *, signing_properties: SigV4SigningProperties, request: AWSRequest @@ -335,11 +338,6 @@ def _normalize_signing_fields(self, *, request: AWSRequest) -> dict[str, str]: for field in request.fields if self._is_signable_header(field.name.lower()) } - if "host" not in normalized_fields: - normalized_fields["host"] = self._normalize_host_field( - uri=request.destination # type: ignore - TODO(pyright) - ) - return dict(sorted(normalized_fields.items())) def _is_signable_header(self, field_name: str): @@ -352,7 +350,10 @@ def _normalize_host_field(self, *, uri: URI) -> str: uri_dict = uri.to_dict() uri_dict.update({"port": None}) uri = URI(**uri_dict) - return uri.netloc + host_header = uri.hostname + if port := uri.port: + host_header += f":{port}" + return host_header def _format_canonical_fields(self, *, fields: dict[str, str]) -> str: return "".join( @@ -601,6 +602,9 @@ async def _apply_required_fields( request.fields.set_field( Field(name="X-Amz-Security-Token", values=[identity.session_token]) ) + if "host" not in request.fields: + host = await self._normalize_host_field(uri=request.destination) + request.fields.set_field(Field(name="host", values=[host])) async def canonical_request( self, *, signing_properties: SigV4SigningProperties, request: AWSRequest @@ -721,10 +725,6 @@ async def _normalize_signing_fields(self, *, request: AWSRequest) -> dict[str, s for field in request.fields if self._is_signable_header(field.name.lower()) } - if "host" not in normalized_fields: - normalized_fields["host"] = await self._normalize_host_field( - uri=request.destination # type: ignore - TODO(pyright) - ) return dict(sorted(normalized_fields.items())) @@ -738,7 +738,10 @@ async def _normalize_host_field(self, *, uri: URI) -> str: uri_dict = uri.to_dict() uri_dict.update({"port": None}) uri = URI(**uri_dict) - return uri.netloc + host_header = uri.hostname + if port := uri.port: + host_header += f":{port}" + return host_header async def _format_canonical_fields(self, *, fields: dict[str, str]) -> str: return "".join( diff --git a/packages/smithy-http/src/smithy_http/aio/crt.py b/packages/smithy-http/src/smithy_http/aio/crt.py index a450ef9c..65b6bc08 100644 --- a/packages/smithy-http/src/smithy_http/aio/crt.py +++ b/packages/smithy-http/src/smithy_http/aio/crt.py @@ -272,9 +272,10 @@ def _marshal_request( :py:class:`smithy_http.aio.HTTPRequest`""" headers_list: list[tuple[str, str]] = [] if "host" not in request.fields: - request.fields.set_field( - Field(name="host", values=[request.destination.netloc]) - ) + host_header = request.destination.hostname + if port := request.destination.port: + host_header += f":{port}" + request.fields.set_field(Field(name="host", values=[host_header])) if "accept" not in request.fields: request.fields.set_field(Field(name="accept", values=["*/*"])) From 142dddd9a1d806b9c1ba8bd5686719194c9fe88e Mon Sep 17 00:00:00 2001 From: SamRemis Date: Fri, 17 Oct 2025 17:06:08 -0400 Subject: [PATCH 05/11] Fix pyright --- packages/aws-sdk-signers/src/aws_sdk_signers/signers.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py index 859e6433..2fc3beb8 100644 --- a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py +++ b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py @@ -17,6 +17,7 @@ from ._http import AWSRequest, Field, URI from ._io import AsyncBytesReader from .exceptions import AWSSDKWarning, MissingExpectedParameterException +from .interfaces.http import URI as InterfaceURI from .interfaces.identity import AWSCredentialsIdentity as _AWSCredentialsIdentity from .interfaces.io import AsyncSeekable, ConditionallySeekable, Seekable @@ -345,12 +346,12 @@ def _is_signable_header(self, field_name: str): return False return True - def _normalize_host_field(self, *, uri: URI) -> str: + def _normalize_host_field(self, *, uri: InterfaceURI) -> str: if uri.port is not None and DEFAULT_PORTS.get(uri.scheme) == uri.port: uri_dict = uri.to_dict() uri_dict.update({"port": None}) uri = URI(**uri_dict) - host_header = uri.hostname + host_header = uri.host if port := uri.port: host_header += f":{port}" return host_header @@ -733,12 +734,12 @@ def _is_signable_header(self, field_name: str): return False return True - async def _normalize_host_field(self, *, uri: URI) -> str: + async def _normalize_host_field(self, *, uri: InterfaceURI) -> str: if uri.port is not None and DEFAULT_PORTS.get(uri.scheme) == uri.port: uri_dict = uri.to_dict() uri_dict.update({"port": None}) uri = URI(**uri_dict) - host_header = uri.hostname + host_header = uri.host if port := uri.port: host_header += f":{port}" return host_header From b65ba40a1207a5ecbe91cadc2ef36ecdd01033c4 Mon Sep 17 00:00:00 2001 From: SamRemis Date: Fri, 17 Oct 2025 17:17:13 -0400 Subject: [PATCH 06/11] more pyright fixes and add changelogs --- .../next-release/aws-sdk-signers-bugfix-20251017171318.json | 4 ++++ packages/aws-sdk-signers/src/aws_sdk_signers/signers.py | 5 ++--- .../next-release/smithy-http-bugfix-20251017171341.json | 4 ++++ packages/smithy-http/src/smithy_http/aio/crt.py | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 packages/aws-sdk-signers/.changes/next-release/aws-sdk-signers-bugfix-20251017171318.json create mode 100644 packages/smithy-http/.changes/next-release/smithy-http-bugfix-20251017171341.json diff --git a/packages/aws-sdk-signers/.changes/next-release/aws-sdk-signers-bugfix-20251017171318.json b/packages/aws-sdk-signers/.changes/next-release/aws-sdk-signers-bugfix-20251017171318.json new file mode 100644 index 00000000..bd9ef6ee --- /dev/null +++ b/packages/aws-sdk-signers/.changes/next-release/aws-sdk-signers-bugfix-20251017171318.json @@ -0,0 +1,4 @@ +{ + "type": "bugfix", + "description": "fix host header port mismatch in signing" +} \ No newline at end of file diff --git a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py index 2fc3beb8..c56f059e 100644 --- a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py +++ b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py @@ -17,7 +17,6 @@ from ._http import AWSRequest, Field, URI from ._io import AsyncBytesReader from .exceptions import AWSSDKWarning, MissingExpectedParameterException -from .interfaces.http import URI as InterfaceURI from .interfaces.identity import AWSCredentialsIdentity as _AWSCredentialsIdentity from .interfaces.io import AsyncSeekable, ConditionallySeekable, Seekable @@ -346,7 +345,7 @@ def _is_signable_header(self, field_name: str): return False return True - def _normalize_host_field(self, *, uri: InterfaceURI) -> str: + def _normalize_host_field(self, *, uri: URI) -> str: if uri.port is not None and DEFAULT_PORTS.get(uri.scheme) == uri.port: uri_dict = uri.to_dict() uri_dict.update({"port": None}) @@ -734,7 +733,7 @@ def _is_signable_header(self, field_name: str): return False return True - async def _normalize_host_field(self, *, uri: InterfaceURI) -> str: + async def _normalize_host_field(self, *, uri: URI) -> str: if uri.port is not None and DEFAULT_PORTS.get(uri.scheme) == uri.port: uri_dict = uri.to_dict() uri_dict.update({"port": None}) diff --git a/packages/smithy-http/.changes/next-release/smithy-http-bugfix-20251017171341.json b/packages/smithy-http/.changes/next-release/smithy-http-bugfix-20251017171341.json new file mode 100644 index 00000000..d8880d55 --- /dev/null +++ b/packages/smithy-http/.changes/next-release/smithy-http-bugfix-20251017171341.json @@ -0,0 +1,4 @@ +{ + "type": "bugfix", + "description": "add port to CRT HTTP client's host header" +} \ No newline at end of file diff --git a/packages/smithy-http/src/smithy_http/aio/crt.py b/packages/smithy-http/src/smithy_http/aio/crt.py index 65b6bc08..4d65dc15 100644 --- a/packages/smithy-http/src/smithy_http/aio/crt.py +++ b/packages/smithy-http/src/smithy_http/aio/crt.py @@ -272,7 +272,7 @@ def _marshal_request( :py:class:`smithy_http.aio.HTTPRequest`""" headers_list: list[tuple[str, str]] = [] if "host" not in request.fields: - host_header = request.destination.hostname + host_header = request.destination.host if port := request.destination.port: host_header += f":{port}" request.fields.set_field(Field(name="host", values=[host_header])) From 9f4486f8c0ce1044780db4ed365b8e6af4f8257a Mon Sep 17 00:00:00 2001 From: SamRemis Date: Fri, 17 Oct 2025 17:20:25 -0400 Subject: [PATCH 07/11] Cleanup dead code --- .../src/aws_sdk_signers/signers.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py index c56f059e..385600a8 100644 --- a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py +++ b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py @@ -99,12 +99,6 @@ def sign( ) signing_fields = self._normalize_signing_fields(request=new_request) - # If any headers have been added, make sure those are reflected in the new request - for field_name, field_value in signing_fields.items(): - if field_name not in request.fields: - new_request.fields.set_field( - Field(name=field_name, values=[field_value]) - ) credential_scope = self._scope(signing_properties=new_signing_properties) credential = f"{identity.access_key_id}/{credential_scope}" authorization = self.generate_authorization_field( @@ -219,7 +213,7 @@ def _apply_required_fields( Field(name="X-Amz-Security-Token", values=[identity.session_token]) ) if "host" not in request.fields: - host = self._normalize_host_field(uri=request.destination) + host = self._normalize_host_field(uri=request.destination) # type: ignore - TODO(pyright) request.fields.set_field(Field(name="host", values=[host])) def canonical_request( @@ -483,12 +477,6 @@ async def sign( ) signing_fields = await self._normalize_signing_fields(request=new_request) - # If any headers have been added, make sure those are reflected in the new request - for field_name, field_value in signing_fields.items(): - if field_name not in request.fields: - new_request.fields.set_field( - Field(name=field_name, values=[field_value]) - ) credential_scope = await self._scope(signing_properties=new_signing_properties) credential = f"{identity.access_key_id}/{credential_scope}" authorization = await self.generate_authorization_field( @@ -603,7 +591,7 @@ async def _apply_required_fields( Field(name="X-Amz-Security-Token", values=[identity.session_token]) ) if "host" not in request.fields: - host = await self._normalize_host_field(uri=request.destination) + host = await self._normalize_host_field(uri=request.destination) # type: ignore - TODO(pyright) request.fields.set_field(Field(name="host", values=[host])) async def canonical_request( From cff2cecf09a3ac7f0eebb45cc24740940dd2fcbb Mon Sep 17 00:00:00 2001 From: SamRemis Date: Tue, 21 Oct 2025 22:31:10 -0400 Subject: [PATCH 08/11] Remove signer changes --- .../src/aws_sdk_signers/signers.py | 25 ++++++++----------- .../tests/unit/test_signers.py | 2 -- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py index 385600a8..29ba0289 100644 --- a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py +++ b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py @@ -212,9 +212,6 @@ def _apply_required_fields( request.fields.set_field( Field(name="X-Amz-Security-Token", values=[identity.session_token]) ) - if "host" not in request.fields: - host = self._normalize_host_field(uri=request.destination) # type: ignore - TODO(pyright) - request.fields.set_field(Field(name="host", values=[host])) def canonical_request( self, *, signing_properties: SigV4SigningProperties, request: AWSRequest @@ -332,6 +329,11 @@ def _normalize_signing_fields(self, *, request: AWSRequest) -> dict[str, str]: for field in request.fields if self._is_signable_header(field.name.lower()) } + if "host" not in normalized_fields: + normalized_fields["host"] = self._normalize_host_field( + uri=request.destination # type: ignore - TODO(pyright) + ) + return dict(sorted(normalized_fields.items())) def _is_signable_header(self, field_name: str): @@ -344,10 +346,7 @@ def _normalize_host_field(self, *, uri: URI) -> str: uri_dict = uri.to_dict() uri_dict.update({"port": None}) uri = URI(**uri_dict) - host_header = uri.host - if port := uri.port: - host_header += f":{port}" - return host_header + return uri.netloc def _format_canonical_fields(self, *, fields: dict[str, str]) -> str: return "".join( @@ -590,9 +589,6 @@ async def _apply_required_fields( request.fields.set_field( Field(name="X-Amz-Security-Token", values=[identity.session_token]) ) - if "host" not in request.fields: - host = await self._normalize_host_field(uri=request.destination) # type: ignore - TODO(pyright) - request.fields.set_field(Field(name="host", values=[host])) async def canonical_request( self, *, signing_properties: SigV4SigningProperties, request: AWSRequest @@ -713,6 +709,10 @@ async def _normalize_signing_fields(self, *, request: AWSRequest) -> dict[str, s for field in request.fields if self._is_signable_header(field.name.lower()) } + if "host" not in normalized_fields: + normalized_fields["host"] = await self._normalize_host_field( + uri=request.destination # type: ignore - TODO(pyright) + ) return dict(sorted(normalized_fields.items())) @@ -726,10 +726,7 @@ async def _normalize_host_field(self, *, uri: URI) -> str: uri_dict = uri.to_dict() uri_dict.update({"port": None}) uri = URI(**uri_dict) - host_header = uri.host - if port := uri.port: - host_header += f":{port}" - return host_header + return uri.netloc async def _format_canonical_fields(self, *, fields: dict[str, str]) -> str: return "".join( diff --git a/packages/aws-sdk-signers/tests/unit/test_signers.py b/packages/aws-sdk-signers/tests/unit/test_signers.py index f71b11de..cafef288 100644 --- a/packages/aws-sdk-signers/tests/unit/test_signers.py +++ b/packages/aws-sdk-signers/tests/unit/test_signers.py @@ -94,8 +94,6 @@ def test_sign_doesnt_modify_original_request( assert signed_request is not aws_request assert aws_request.fields == original_request.fields assert signed_request.fields != aws_request.fields - assert "host" in signed_request.fields - assert "authorization" in signed_request.fields @typing.no_type_check def test_sign_with_invalid_identity( From ee59054ef0d99f9db72c4c9f30875afd28c752f1 Mon Sep 17 00:00:00 2001 From: SamRemis Date: Tue, 21 Oct 2025 22:57:12 -0400 Subject: [PATCH 09/11] Updates based on PR feedback --- packages/smithy-http/src/smithy_http/aio/crt.py | 7 +++---- packages/smithy-http/tests/unit/aio/test_crt.py | 13 ++++++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/smithy-http/src/smithy_http/aio/crt.py b/packages/smithy-http/src/smithy_http/aio/crt.py index 4d65dc15..a450ef9c 100644 --- a/packages/smithy-http/src/smithy_http/aio/crt.py +++ b/packages/smithy-http/src/smithy_http/aio/crt.py @@ -272,10 +272,9 @@ def _marshal_request( :py:class:`smithy_http.aio.HTTPRequest`""" headers_list: list[tuple[str, str]] = [] if "host" not in request.fields: - host_header = request.destination.host - if port := request.destination.port: - host_header += f":{port}" - request.fields.set_field(Field(name="host", values=[host_header])) + request.fields.set_field( + Field(name="host", values=[request.destination.netloc]) + ) if "accept" not in request.fields: request.fields.set_field(Field(name="accept", values=["*/*"])) diff --git a/packages/smithy-http/tests/unit/aio/test_crt.py b/packages/smithy-http/tests/unit/aio/test_crt.py index 89eacbce..6472a437 100644 --- a/packages/smithy-http/tests/unit/aio/test_crt.py +++ b/packages/smithy-http/tests/unit/aio/test_crt.py @@ -45,18 +45,25 @@ def test_client_marshal_request() -> None: assert crt_request.path == "/path?key1=value1&key2=value2" -async def test_port_included_in_host_header() -> None: +@pytest.mark.parametrize( + "host,expected", + [ + ("example.com", "example.com:8443"), + ("2001:db8::1", "[2001:db8::1]:8443"), + ], +) +async def test_port_included_in_host_header(host: str, expected: str) -> None: client = AWSCRTHTTPClient() request = HTTPRequest( method="GET", destination=URI( - host="example.com", path="/path", query="key1=value1&key2=value2", port=8443 + host=host, path="/path", query="key1=value1&key2=value2", port=8443 ), body=BytesIO(), fields=Fields(), ) crt_request, _ = await client._marshal_request(request) # type: ignore - assert crt_request.headers.get("host") == "example.com:8443" # type: ignore + assert crt_request.headers.get("host") == expected # type: ignore async def test_body_generator_bytes() -> None: From 2b60ae66b1ae38ec5f4276b7c03e1e4b78245c68 Mon Sep 17 00:00:00 2001 From: SamRemis Date: Tue, 21 Oct 2025 22:58:09 -0400 Subject: [PATCH 10/11] remove old changelog --- .../next-release/aws-sdk-signers-bugfix-20251017171318.json | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 packages/aws-sdk-signers/.changes/next-release/aws-sdk-signers-bugfix-20251017171318.json diff --git a/packages/aws-sdk-signers/.changes/next-release/aws-sdk-signers-bugfix-20251017171318.json b/packages/aws-sdk-signers/.changes/next-release/aws-sdk-signers-bugfix-20251017171318.json deleted file mode 100644 index bd9ef6ee..00000000 --- a/packages/aws-sdk-signers/.changes/next-release/aws-sdk-signers-bugfix-20251017171318.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "type": "bugfix", - "description": "fix host header port mismatch in signing" -} \ No newline at end of file From 6eafa425ec16751427c6a02c7f48799c46862faf Mon Sep 17 00:00:00 2001 From: SamRemis Date: Wed, 22 Oct 2025 16:47:41 -0400 Subject: [PATCH 11/11] adding required updates after rebase --- packages/smithy-http/tests/unit/aio/test_crt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/smithy-http/tests/unit/aio/test_crt.py b/packages/smithy-http/tests/unit/aio/test_crt.py index 6472a437..886bb5f2 100644 --- a/packages/smithy-http/tests/unit/aio/test_crt.py +++ b/packages/smithy-http/tests/unit/aio/test_crt.py @@ -62,7 +62,7 @@ async def test_port_included_in_host_header(host: str, expected: str) -> None: body=BytesIO(), fields=Fields(), ) - crt_request, _ = await client._marshal_request(request) # type: ignore + crt_request = client._marshal_request(request) # type: ignore assert crt_request.headers.get("host") == expected # type: ignore