|
12 | 12 | import boto3 |
13 | 13 | import requests |
14 | 14 | from botocore.awsrequest import AWSPreparedRequest |
15 | | -from botocore.model import OperationModel |
| 15 | +from botocore.model import OperationModel, ServiceModel |
| 16 | +from botocore.session import get_session as get_botocore_session |
| 17 | +from localstack.aws.protocol.parser import create_parser |
| 18 | +from localstack.aws.spec import load_service |
16 | 19 | from localstack import config as localstack_config |
17 | 20 | from localstack.config import external_service_url |
18 | 21 | from localstack.constants import ( |
|
43 | 46 | from aws_proxy import config as repl_config |
44 | 47 | from aws_proxy.client.utils import truncate_content |
45 | 48 | from aws_proxy.config import HANDLER_PATH_PROXIES |
46 | | -from aws_proxy.shared.constants import HEADER_HOST_ORIGINAL |
| 49 | +from aws_proxy.shared.constants import HEADER_HOST_ORIGINAL, SERVICE_NAME_MAPPING |
47 | 50 | from aws_proxy.shared.models import AddProxyRequest, ProxyConfig |
48 | 51 |
|
49 | 52 | LOG = logging.getLogger(__name__) |
50 | 53 | LOG.setLevel(logging.INFO) |
51 | 54 | if localstack_config.DEBUG: |
52 | 55 | LOG.setLevel(logging.DEBUG) |
53 | 56 |
|
54 | | -# Mapping from AWS service signing names to boto3 client names |
55 | | -SERVICE_NAME_MAPPING = { |
56 | | - "monitoring": "cloudwatch", |
57 | | -} |
58 | 57 |
|
59 | 58 | # TODO make configurable |
60 | 59 | CLI_PIP_PACKAGE = "localstack-extension-aws-proxy" |
@@ -197,13 +196,19 @@ def deregister_from_instance(self): |
197 | 196 | def _parse_aws_request( |
198 | 197 | self, request: Request, service_name: str, region_name: str, client |
199 | 198 | ) -> Tuple[OperationModel, AWSPreparedRequest, Dict]: |
200 | | - from localstack.aws.protocol.parser import create_parser |
| 199 | + # Use LocalStack's load_service for parsing, as it handles multi-protocol detection |
| 200 | + # from request headers (e.g., detecting JSON vs RPC v2 CBOR from content-type). |
| 201 | + localstack_service_model = load_service(service_name) |
| 202 | + parser = create_parser(localstack_service_model) |
| 203 | + ls_operation_model, parsed_request = parser.parse(request) |
| 204 | + |
| 205 | + # Get botocore's operation model for making the actual AWS request, |
| 206 | + # as botocore client methods expect botocore model objects. |
| 207 | + botocore_service_model = self._get_botocore_service_model(service_name) |
| 208 | + operation_model = botocore_service_model.operation_model( |
| 209 | + ls_operation_model.name |
| 210 | + ) |
201 | 211 |
|
202 | | - # Use botocore's service model to ensure protocol compatibility |
203 | | - # (LocalStack's load_service may return newer protocol versions that don't match the client) |
204 | | - service_model = self._get_botocore_service_model(service_name) |
205 | | - parser = create_parser(service_model) |
206 | | - operation_model, parsed_request = parser.parse(request) |
207 | 212 | request_context = { |
208 | 213 | "client_region": region_name, |
209 | 214 | "has_streaming_input": operation_model.has_streaming_input, |
@@ -348,10 +353,7 @@ def _get_botocore_service_model(service_name: str): |
348 | 353 | load_service() to ensure protocol compatibility, as LocalStack may use newer protocol |
349 | 354 | versions (e.g., smithy-rpc-v2-cbor) while clients use older protocols (e.g., query). |
350 | 355 | """ |
351 | | - import botocore.session |
352 | | - from botocore.model import ServiceModel |
353 | | - |
354 | | - session = botocore.session.get_session() |
| 356 | + session = get_botocore_session() |
355 | 357 | loader = session.get_component("data_loader") |
356 | 358 | api_data = loader.load_service_model(service_name, "service-2") |
357 | 359 | return ServiceModel(api_data) |
|
0 commit comments