Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.

Commit 3ff3e2a

Browse files
authored
fix proxied requests forwarding to Moto (#11653)
1 parent 87104a6 commit 3ff3e2a

2 files changed

Lines changed: 38 additions & 4 deletions

File tree

localstack-core/localstack/services/moto.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,17 @@ def dispatch_to_moto(context: RequestContext) -> Response:
108108
service = context.service
109109
request = context.request
110110

111+
# Werkzeug might have an issue (to be determined where the responsibility lies) with proxied requests where the
112+
# HTTP location is a full URI and not only a path.
113+
# We need to use the full_raw_url as moto does some path decoding (in S3 for example)
114+
full_raw_path = get_full_raw_path(request)
115+
# remove the query string from the full path to do the matching of the request
116+
raw_path_only = full_raw_path.split("?")[0]
111117
# this is where we skip the HTTP roundtrip between the moto server and the boto client
112-
dispatch = get_dispatcher(service.service_name, request.path)
118+
dispatch = get_dispatcher(service.service_name, raw_path_only)
113119
try:
114-
# we use the full_raw_url as moto might do some path decoding (in S3 for example)
115120
raw_url = get_raw_current_url(
116-
request.scheme, request.host, request.root_path, get_full_raw_path(request)
121+
request.scheme, request.host, request.root_path, full_raw_path
117122
)
118123
response = dispatch(request, raw_url, request.headers)
119124
if not response:

tests/aws/test_moto.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33

44
import pytest
55
from moto.core import DEFAULT_ACCOUNT_ID as DEFAULT_MOTO_ACCOUNT_ID
6+
from rolo import Request
67

78
import localstack.aws.accounts
8-
from localstack.aws.api import ServiceException, handler
9+
from localstack.aws.api import RequestContext, ServiceException, handler
910
from localstack.aws.forwarder import NotImplementedAvoidFallbackError
11+
from localstack.aws.spec import load_service
1012
from localstack.constants import AWS_REGION_US_EAST_1
1113
from localstack.services import moto
1214
from localstack.services.moto import MotoFallbackDispatcher
@@ -229,6 +231,33 @@ def test_call_with_sqs_returns_service_response():
229231
assert create_queue_response["QueueUrl"].endswith(qname)
230232

231233

234+
@markers.aws.only_localstack
235+
def test_call_with_sns_with_full_uri():
236+
# when requests are being forwarded by a Proxy, the HTTP request can contain the full URI and not only the path
237+
# see https://github.com/localstack/localstack/pull/8962
238+
# by using `request.path`, we would use a full URI in the request, as Werkzeug has issue parsing those proxied
239+
# requests
240+
topic_name = f"queue-{short_uid()}"
241+
sns_request = Request(
242+
"POST",
243+
"/",
244+
raw_path="http://localhost:4566/",
245+
body=f"Action=CreateTopic&Name={topic_name}&Version=2010-03-31",
246+
headers={"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"},
247+
)
248+
sns_service = load_service("sns")
249+
context = RequestContext()
250+
context.account = "test"
251+
context.region = "us-west-1"
252+
context.service = sns_service
253+
context.request = sns_request
254+
context.operation = sns_service.operation_model("CreateTopic")
255+
256+
create_topic_response = moto.call_moto(context)
257+
258+
assert create_topic_response["TopicArn"].endswith(topic_name)
259+
260+
232261
class FakeSqsApi:
233262
@handler("ListQueues", expand=False)
234263
def list_queues(self, context, request):

0 commit comments

Comments
 (0)