Skip to content

Commit b982094

Browse files
author
IlyaFaer
committed
feat: add helper for bucket bound hostname URLs
1 parent d84c0dd commit b982094

5 files changed

Lines changed: 60 additions & 20 deletions

File tree

google/cloud/storage/_helpers.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,25 @@ def _convert_to_timestamp(value):
312312
utc_naive = value.replace(tzinfo=None) - value.utcoffset()
313313
mtime = (utc_naive - datetime(1970, 1, 1)).total_seconds()
314314
return mtime
315+
316+
317+
def _bucket_bound_hostname_url(host, scheme=None, end_slash=False):
318+
"""Helper to build bucket bound hostname URL.
319+
320+
:type host: str
321+
:param host: Host name.
322+
323+
:type scheme: str
324+
:param scheme: (Optional) Web scheme. If passed, use it
325+
as a scheme in the result URL.
326+
327+
:type end_slash: bool
328+
:param end_slash: (Optional) If True, add "/" slash to
329+
the end of the result URL.
330+
"""
331+
if ":" in host:
332+
return host
333+
334+
return "{scheme}://{host}{slash}".format(
335+
scheme=scheme, host=host, slash="/" if end_slash else ""
336+
)

google/cloud/storage/blob.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
from google.cloud.exceptions import NotFound
5757
from google.cloud.storage._helpers import _PropertyMixin
5858
from google.cloud.storage._helpers import _scalar_property
59+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
5960
from google.cloud.storage._helpers import _convert_to_timestamp
6061
from google.cloud.storage._signing import generate_signed_url_v2
6162
from google.cloud.storage._signing import generate_signed_url_v4
@@ -514,12 +515,9 @@ def generate_signed_url(
514515
bucket_name=self.bucket.name
515516
)
516517
elif bucket_bound_hostname:
517-
if ":" in bucket_bound_hostname:
518-
api_access_endpoint = bucket_bound_hostname
519-
else:
520-
api_access_endpoint = "{scheme}://{bucket_bound_hostname}".format(
521-
scheme=scheme, bucket_bound_hostname=bucket_bound_hostname
522-
)
518+
api_access_endpoint = _bucket_bound_hostname_url(
519+
bucket_bound_hostname, scheme
520+
)
523521
else:
524522
resource = "/{bucket_name}/{quoted_name}".format(
525523
bucket_name=self.bucket.name, quoted_name=quoted_name

google/cloud/storage/bucket.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from google.cloud.storage._helpers import _validate_name
3838
from google.cloud.storage._signing import generate_signed_url_v2
3939
from google.cloud.storage._signing import generate_signed_url_v4
40+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
4041
from google.cloud.storage.acl import BucketACL
4142
from google.cloud.storage.acl import DefaultObjectACL
4243
from google.cloud.storage.blob import Blob
@@ -2560,12 +2561,9 @@ def generate_signed_url(
25602561
bucket_name=self.name
25612562
)
25622563
elif bucket_bound_hostname:
2563-
if ":" in bucket_bound_hostname:
2564-
api_access_endpoint = bucket_bound_hostname
2565-
else:
2566-
api_access_endpoint = "{scheme}://{bucket_bound_hostname}".format(
2567-
scheme=scheme, bucket_bound_hostname=bucket_bound_hostname
2568-
)
2564+
api_access_endpoint = _bucket_bound_hostname_url(
2565+
bucket_bound_hostname, scheme
2566+
)
25692567
else:
25702568
resource = "/{bucket_name}".format(bucket_name=self.name)
25712569

google/cloud/storage/client.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from google.cloud.client import ClientWithProject
3131
from google.cloud.exceptions import NotFound
3232
from google.cloud.storage._helpers import _get_storage_host
33+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
3334
from google.cloud.storage._http import Connection
3435
from google.cloud.storage._signing import (
3536
get_expiration_seconds_v4,
@@ -1033,15 +1034,10 @@ def generate_signed_post_policy_v4(
10331034
# designate URL
10341035
if virtual_hosted_style:
10351036
url = "https://{}.storage.googleapis.com/".format(bucket_name)
1036-
10371037
elif bucket_bound_hostname:
1038-
if ":" in bucket_bound_hostname: # URL includes scheme
1039-
url = bucket_bound_hostname
1040-
1041-
else: # scheme is given separately
1042-
url = "{scheme}://{host}/".format(
1043-
scheme=scheme, host=bucket_bound_hostname
1044-
)
1038+
url = _bucket_bound_hostname_url(
1039+
bucket_bound_hostname, scheme, end_slash=True
1040+
)
10451041
else:
10461042
url = "https://storage.googleapis.com/{}/".format(bucket_name)
10471043

tests/unit/test__helpers.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,32 @@ def read(self, block_size):
342342
self.assertEqual(MD5.hash_obj.num_digest_calls, 1)
343343
self.assertEqual(MD5.hash_obj._blocks, [BYTES_TO_SIGN])
344344

345+
class Test__bucket_bound_hostname_url(unittest.TestCase):
346+
def _call_fut(self, **args):
347+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
348+
349+
return _bucket_bound_hostname_url(**args)
350+
351+
def test_full_hostname(self):
352+
HOST = "scheme://domain.tcl"
353+
self.assertEqual(self._call_fut(host=HOST), HOST)
354+
355+
def test_hostname_and_scheme(self):
356+
HOST = "domain.tcl"
357+
SCHEME = "scheme"
358+
EXPECTED_URL = SCHEME + "://" + HOST
359+
360+
self.assertEqual(self._call_fut(host=HOST, scheme=SCHEME), EXPECTED_URL)
361+
362+
def test_with_end_slash(self):
363+
HOST = "domain.tcl"
364+
SCHEME = "scheme"
365+
EXPECTED_URL = "{scheme}://{host}/".format(scheme=SCHEME, host=HOST)
366+
367+
self.assertEqual(
368+
self._call_fut(host=HOST, scheme=SCHEME, end_slash=True), EXPECTED_URL
369+
)
370+
345371

346372
class _Connection(object):
347373
def __init__(self, *responses):

0 commit comments

Comments
 (0)