Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix internal botocore API usage #7086

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 11 commits into from
Dec 23, 2022
24 changes: 21 additions & 3 deletions localstack/aws/forwarder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import Any, Callable, Mapping, Optional
from urllib.parse import urlsplit

from botocore.awsrequest import AWSPreparedRequest
from botocore.awsrequest import AWSPreparedRequest, prepare_request_dict
from botocore.config import Config as BotoConfig
from werkzeug.datastructures import Headers

Expand Down Expand Up @@ -164,9 +164,27 @@ def create_aws_request_context(
"has_streaming_input": operation.has_streaming_input,
"auth_type": operation.auth_type,
}
request_dict = client._convert_to_request_dict(parameters, operation, context=request_context)
aws_request = client._endpoint.create_request(request_dict, operation)

# The endpoint URL is mandatory here, set a dummy if not given (doesn't _need_ to be localstack specific)
if not endpoint_url:
endpoint_url = "http://localhost.localstack.cloud"
request_dict = client._convert_to_request_dict(
parameters, operation, endpoint_url, context=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.
# Afterwards the request needs to be prepared again.
request_dict["url_path"] = auth_path
prepare_request_dict(
request_dict,
endpoint_url=endpoint_url,
user_agent=client._client_config.user_agent,
context=request_context,
)

aws_request: AWSPreparedRequest = client._endpoint.create_request(request_dict, operation)
context = RequestContext()
context.service = service
context.operation = operation
Expand Down
9 changes: 8 additions & 1 deletion localstack/aws/protocol/op_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@ class _HttpOperation(NamedTuple):

@staticmethod
def from_operation(op: OperationModel) -> "_HttpOperation":
uri = op.http.get("requestUri")
# botocore >= 1.28 might modify the internal model (specifically for S3).
# It will modify the request URI and set the original value at "authPath".
# Use authPath if set, otherwise use the regular requestUri.
if auth_path := op.http.get("authPath"):
uri = auth_path.rstrip("/")
else:
uri = op.http.get("requestUri")

method = op.http.get("method")
deprecated = op.deprecated

Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ packages=find:

# dependencies that are required for the cli (via pip install localstack)
install_requires =
boto3>=1.20,<1.25.0
boto3>=1.25.0
click>=7.0
cachetools~=5.0.0
#dnspython==1.16.0
Expand Down Expand Up @@ -67,7 +67,7 @@ runtime =
awscli>=1.22.90
awscrt>=0.13.14
boto>=2.49.0
botocore>=1.12.13,<1.28.0
botocore>=1.28.0
cbor2>=5.2.0
crontab>=0.22.6
cryptography
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/aws/protocol/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,12 @@ def _botocore_parser_integration_test(

operation_model = service.operation_model(action)
serialized_request = serializer.serialize_to_request(kwargs, operation_model)

# 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.
if auth_path := serialized_request.get("auth_path"):
serialized_request["url_path"] = auth_path

prepare_request_dict(serialized_request, "")
split_url = urlsplit(serialized_request.get("url"))
path = split_url.path
Expand Down
11 changes: 10 additions & 1 deletion tests/unit/aws/test_service_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ def _collect_operations() -> Tuple[ServiceModel, OperationModel]:
"chime-sdk-media-pipelines",
"chime-sdk-meetings",
"chime-sdk-messaging",
"chime-sdk-voice",
"codecatalyst",
"connect",
"connect-contact-lens",
"greengrassv2",
Expand All @@ -40,6 +42,7 @@ def _collect_operations() -> Tuple[ServiceModel, OperationModel]:
"kinesis-video-archived-media",
"kinesis-video-media",
"kinesis-video-signaling",
"kinesis-video-webrtc-storage",
"kinesisvideo",
"lex-models",
"lex-runtime",
Expand All @@ -51,9 +54,11 @@ def _collect_operations() -> Tuple[ServiceModel, OperationModel]:
"pinpoint-sms-voice",
"sagemaker-edge",
"sagemaker-featurestore-runtime",
"sagemaker-metrics",
"sms-voice",
"sso",
"sso-oidc",
"workdocs",
]:
yield pytest.param(
service,
Expand Down Expand Up @@ -164,7 +169,11 @@ def test_service_router_works_for_every_service(
"auth_type": operation.auth_type,
}
request_args = _create_dummy_request_args(operation)
request_dict = client._convert_to_request_dict(request_args, operation, request_context)

# The endpoint URL is mandatory here, just set a dummy (doesn't _need_ to be localstack specific)
request_dict = client._convert_to_request_dict(
request_args, operation, "http://localhost.localstack.cloud", request_context
)
request_object = create_request_object(request_dict)
client._request_signer.sign(operation.name, request_object)
request: Request = _botocore_request_to_localstack_request(request_object)
Expand Down