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

Commit cc8cc23

Browse files
authored
S3: clean up leftover legacy code (#13271)
1 parent 1913637 commit cc8cc23

5 files changed

Lines changed: 20 additions & 46 deletions

File tree

localstack-core/localstack/services/s3/constants.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
)
1111
from localstack.aws.api.s3 import Type as GranteeType
1212

13-
S3_VIRTUAL_HOST_FORWARDED_HEADER = "x-s3-vhost-forwarded-for"
14-
1513
S3_UPLOAD_PART_MIN_SIZE = 5242880
1614
"""
1715
This is minimum size allowed by S3 when uploading more than one part for a Multipart Upload, except for the last part

localstack-core/localstack/services/s3/notifications.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class S3EventNotificationContext:
105105
key_storage_class: StorageClass | None
106106

107107
@classmethod
108-
def from_request_context_native(
108+
def from_request_context(
109109
cls,
110110
request_context: RequestContext,
111111
s3_bucket: S3Bucket,

localstack-core/localstack/services/s3/presigned_url.py

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,8 @@
4545
SIGNATURE_V4_PARAMS,
4646
)
4747
from localstack.services.s3.utils import (
48-
S3_VIRTUAL_HOST_FORWARDED_HEADER,
4948
capitalize_header_name_from_snake_case,
5049
extract_bucket_name_and_key_from_headers_and_path,
51-
forwarded_from_virtual_host_addressed_request,
5250
is_bucket_name_valid,
5351
is_presigned_url_request,
5452
uses_host_addressing,
@@ -567,34 +565,21 @@ def __init__(self, context: RequestContext):
567565
self._query_parameters
568566
)
569567

570-
if forwarded_from_virtual_host_addressed_request(self._headers):
571-
# FIXME: maybe move this so it happens earlier in the chain when using virtual host?
572-
if not is_bucket_name_valid(self._bucket):
573-
raise InvalidBucketName(BucketName=self._bucket)
574-
netloc = self._headers.get(S3_VIRTUAL_HOST_FORWARDED_HEADER)
575-
self.host = netloc
576-
self._original_host = netloc
577-
self.signed_headers["host"] = netloc
578-
# the request comes from the Virtual Host router, we need to remove the bucket from the path
568+
netloc = urlparse.urlparse(self.request.url).netloc
569+
self.host = netloc
570+
self._original_host = netloc
571+
if (host_addressed := uses_host_addressing(self._headers)) and not is_bucket_name_valid(
572+
self._bucket
573+
):
574+
raise InvalidBucketName(BucketName=self._bucket)
575+
576+
if not host_addressed and not self.request.path.startswith(f"/{self._bucket}"):
577+
# if in path style, check that the path starts with the bucket
578+
# our path has been sanitized, we should use the un-sanitized one
579579
splitted_path = self.request.path.split("/", maxsplit=2)
580-
self.path = f"/{splitted_path[-1]}"
581-
580+
self.path = f"/{self._bucket}/{splitted_path[-1]}"
582581
else:
583-
netloc = urlparse.urlparse(self.request.url).netloc
584-
self.host = netloc
585-
self._original_host = netloc
586-
if (host_addressed := uses_host_addressing(self._headers)) and not is_bucket_name_valid(
587-
self._bucket
588-
):
589-
raise InvalidBucketName(BucketName=self._bucket)
590-
591-
if not host_addressed and not self.request.path.startswith(f"/{self._bucket}"):
592-
# if in path style, check that the path starts with the bucket
593-
# our path has been sanitized, we should use the un-sanitized one
594-
splitted_path = self.request.path.split("/", maxsplit=2)
595-
self.path = f"/{self._bucket}/{splitted_path[-1]}"
596-
else:
597-
self.path = self.request.path
582+
self.path = self.request.path
598583

599584
# we need to URL encode the path, as the key needs to be urlencoded for the signature to match
600585
self.path = urlparse.quote(self.path)

localstack-core/localstack/services/s3/provider.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ def _notify(
384384
"""
385385
if s3_bucket.notification_configuration:
386386
if not s3_notif_ctx:
387-
s3_notif_ctx = S3EventNotificationContext.from_request_context_native(
387+
s3_notif_ctx = S3EventNotificationContext.from_request_context(
388388
context,
389389
s3_bucket=s3_bucket,
390390
s3_object=s3_object,
@@ -1271,7 +1271,7 @@ def delete_object(
12711271
delete_marker_id = generate_version_id(s3_bucket.versioning_status)
12721272
delete_marker = S3DeleteMarker(key=key, version_id=delete_marker_id)
12731273
s3_bucket.objects.set(key, delete_marker)
1274-
s3_notif_ctx = S3EventNotificationContext.from_request_context_native(
1274+
s3_notif_ctx = S3EventNotificationContext.from_request_context(
12751275
context,
12761276
s3_bucket=s3_bucket,
12771277
s3_object=delete_marker,
@@ -1374,7 +1374,7 @@ def delete_objects(
13741374
delete_marker_id = generate_version_id(s3_bucket.versioning_status)
13751375
delete_marker = S3DeleteMarker(key=object_key, version_id=delete_marker_id)
13761376
s3_bucket.objects.set(object_key, delete_marker)
1377-
s3_notif_ctx = S3EventNotificationContext.from_request_context_native(
1377+
s3_notif_ctx = S3EventNotificationContext.from_request_context(
13781378
context,
13791379
s3_bucket=s3_bucket,
13801380
s3_object=delete_marker,
@@ -2202,7 +2202,7 @@ def restore_object(
22022202
# TODO: add a way to transition from ongoing-request=true to false? for now it is instant
22032203
s3_object.restore = f'ongoing-request="false", expiry-date="{restore_expiration_date}"'
22042204

2205-
s3_notif_ctx_initiated = S3EventNotificationContext.from_request_context_native(
2205+
s3_notif_ctx_initiated = S3EventNotificationContext.from_request_context(
22062206
context,
22072207
s3_bucket=s3_bucket,
22082208
s3_object=s3_object,

localstack-core/localstack/services/s3/utils.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import re
88
import time
99
import zlib
10+
from collections.abc import Mapping
1011
from enum import StrEnum
1112
from secrets import token_bytes
1213
from typing import Any, Literal, NamedTuple, Protocol
@@ -63,7 +64,6 @@
6364
AUTHENTICATED_USERS_ACL_GRANTEE,
6465
CHECKSUM_ALGORITHMS,
6566
LOG_DELIVERY_ACL_GRANTEE,
66-
S3_VIRTUAL_HOST_FORWARDED_HEADER,
6767
SIGNATURE_V2_PARAMS,
6868
SIGNATURE_V4_PARAMS,
6969
SYSTEM_METADATA_SETTABLE_HEADERS,
@@ -522,7 +522,7 @@ def is_valid_canonical_id(canonical_id: str) -> bool:
522522
return False
523523

524524

525-
def uses_host_addressing(headers: dict[str, str]) -> str | None:
525+
def uses_host_addressing(headers: Mapping[str, str]) -> str | None:
526526
"""
527527
Determines if the request is targeting S3 with virtual host addressing
528528
:param headers: the request headers
@@ -551,15 +551,6 @@ def get_system_metadata_from_request(request: dict) -> Metadata:
551551
return metadata
552552

553553

554-
def forwarded_from_virtual_host_addressed_request(headers: dict[str, str]) -> bool:
555-
"""
556-
Determines if the request was forwarded from a v-host addressing style into a path one
557-
"""
558-
# we can assume that the host header we are receiving here is actually the header we originally received
559-
# from the client (because the edge service is forwarding the request in memory)
560-
return S3_VIRTUAL_HOST_FORWARDED_HEADER in headers
561-
562-
563554
def extract_bucket_name_and_key_from_headers_and_path(
564555
headers: dict[str, str], path: str
565556
) -> tuple[str | None, str | None]:

0 commit comments

Comments
 (0)