From 9232d8f514d8f1fa3b11a14d66d80e814a8a44d2 Mon Sep 17 00:00:00 2001 From: Brendon Smith Date: Sun, 14 Jan 2024 15:03:31 -0500 Subject: [PATCH] Remove scheme from `bucket_host` The `fastenv.cloud.object_storage.ObjectStorageConfig` class is used to configure fastenv for connecting to object storage buckets. The class accepts a `bucket_host` in "virtual-hosted-style," like `.s3..amazonaws.com` for AWS S3 or `.s3..backblazeb2.com` for Backblaze B2. Object storage buckets commonly have HTTPS endpoints, and therefore some users may prepend the scheme ("https://") to their `bucket_host`. The scheme should be removed if present because it is added automatically when generating instances of `httpx.URL()`. This commit will update `fastenv.cloud.object_storage.ObjectStorageConfig` to remove the scheme. https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html --- fastenv/cloud/object_storage.py | 16 ++++++++++++---- tests/cloud/test_object_storage.py | 25 ++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/fastenv/cloud/object_storage.py b/fastenv/cloud/object_storage.py index 5199867..d557c2b 100644 --- a/fastenv/cloud/object_storage.py +++ b/fastenv/cloud/object_storage.py @@ -77,10 +77,18 @@ def __init__( "`.s3..backblazeb2.com` for Backblaze B2." ) elif bucket_host and not bucket_name: - if ( - bucket_host.endswith(".amazonaws.com") - or bucket_host.endswith(".backblazeb2.com") - ) and bucket_name is None: + scheme = ( + "http://" + if bucket_host.startswith("http://") + else "https://" + if bucket_host.startswith("https://") + else None + ) + if scheme: + bucket_host = bucket_host.split(scheme, maxsplit=1)[1] + if bucket_host.endswith(".amazonaws.com") or bucket_host.endswith( + ".backblazeb2.com" + ): self.bucket_name = bucket_host.split(".s3.")[0] else: self.bucket_name = None diff --git a/tests/cloud/test_object_storage.py b/tests/cloud/test_object_storage.py index 5fc86fb..6aac73d 100644 --- a/tests/cloud/test_object_storage.py +++ b/tests/cloud/test_object_storage.py @@ -243,10 +243,10 @@ def test_config_if_not_bucket_name( bucket_name=bucket_name, bucket_region=bucket_region, ) - if "backblazeb2" in bucket_host and bucket_name is None: - assert config.bucket_name == "mybucket" - else: + if "digitaloceanspaces.com" in bucket_host: assert config.bucket_name is None + else: + assert config.bucket_name == self.example_bucket_name def test_config_if_bucket_name_not_in_bucket_host( self, mocker: MockerFixture @@ -295,6 +295,25 @@ def test_config_if_bucket_region_not_in_bucket_host( ) assert str(e.value) == expected_exception_value + @pytest.mark.parametrize("scheme", ("http", "https")) + def test_config_if_scheme_in_bucket_host( + self, scheme: str, mocker: MockerFixture + ) -> None: + """Assert that bucket host scheme ("http" or "https") is removed if present. + Scheme is added automatically when generating instances of `httpx.URL()`. + """ + mocker.patch.dict(os.environ, clear=True) + bucket_host = f"{scheme}://{self.example_bucket_host}" + expected_bucket_host = self.example_bucket_host + config = fastenv.cloud.object_storage.ObjectStorageConfig( + access_key=self.example_access_key, + secret_key=self.example_secret_key, + bucket_host=bucket_host, + bucket_region=self.example_bucket_region, + ) + assert self.config_is_correct(config, expected_bucket_host=expected_bucket_host) + assert scheme not in config.bucket_host + class TestObjectStorageClientUnit: """Test `class ObjectStorageClient` and its methods.