diff --git a/localstack/aws/forwarder.py b/localstack/aws/forwarder.py index 18737f89edbd9..e2e8383c40c7c 100644 --- a/localstack/aws/forwarder.py +++ b/localstack/aws/forwarder.py @@ -184,8 +184,11 @@ def create_aws_request_context( if auth_path := request_dict.get("auth_path"): # botocore >= 1.28 might modify the url path of the request dict (specifically for S3). # It will then set the original url path as "auth_path". If the auth_path is set, we reset the url_path. + # Since botocore 1.31.2, botocore will strip the query from the `authPart` + # We need to add it back from `requestUri` field # Afterwards the request needs to be prepared again. - request_dict["url_path"] = auth_path + path, sep, query = request_dict["url_path"].partition("?") + request_dict["url_path"] = f"{auth_path}{sep}{query}" prepare_request_dict( request_dict, endpoint_url=endpoint_url, diff --git a/localstack/aws/protocol/op_router.py b/localstack/aws/protocol/op_router.py index d9be6aa269ab6..3d4934f80c8b1 100644 --- a/localstack/aws/protocol/op_router.py +++ b/localstack/aws/protocol/op_router.py @@ -39,10 +39,14 @@ class _HttpOperation(NamedTuple): @staticmethod def from_operation(op: OperationModel) -> "_HttpOperation": # botocore >= 1.28 might modify the internal model (specifically for S3). - # It will modify the request URI and set the original value at "authPath". + # It will modify the request URI to strip the bucket name from the path and set the original value at + # "authPath". + # Since botocore 1.31.2, botocore will strip the query from the `authPart` + # We need to add it back from `requestUri` field # Use authPath if set, otherwise use the regular requestUri. if auth_path := op.http.get("authPath"): - uri = auth_path.rstrip("/") + path, sep, query = op.http.get("requestUri", "").partition("?") + uri = f"{auth_path.rstrip('/')}{sep}{query}" else: uri = op.http.get("requestUri") diff --git a/setup.cfg b/setup.cfg index d79432c0a4b81..b2a3e7abd3944 100644 --- a/setup.cfg +++ b/setup.cfg @@ -70,7 +70,7 @@ runtime = awscrt>=0.13.14 boto>=2.49.0 boto3>=1.26.121 - botocore>=1.29.133 + botocore>=1.31.2 cbor2>=5.2.0 crontab>=0.22.6 dnslib>=0.9.10 diff --git a/tests/unit/aws/protocol/test_parser.py b/tests/unit/aws/protocol/test_parser.py index 1720c89f9207e..4536cb55f4738 100644 --- a/tests/unit/aws/protocol/test_parser.py +++ b/tests/unit/aws/protocol/test_parser.py @@ -305,8 +305,11 @@ def _botocore_parser_integration_test( # botocore >= 1.28 might modify the url path of the request dict (specifically for S3). # It will then set the original url path as "auth_path". If the auth_path is set, we reset the url_path. + # Since botocore 1.31.2, botocore will strip the query from the `authPart` + # We need to add it back from `requestUri` field if auth_path := serialized_request.get("auth_path"): - serialized_request["url_path"] = auth_path + path, sep, query = serialized_request["url_path"].partition("?") + serialized_request["url_path"] = f"{auth_path}{sep}{query}" prepare_request_dict(serialized_request, "") split_url = urlsplit(serialized_request.get("url"))