Skip to content

Commit b26f9fa

Browse files
author
Gurov Ilya
authored
feat: add helper for bucket bound hostname URLs (#137)
Closes #121
1 parent e516ed9 commit b26f9fa

File tree

7 files changed

+57
-32
lines changed

7 files changed

+57
-32
lines changed

google/cloud/storage/_helpers.py

+21
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from datetime import datetime
2323
import os
2424

25+
from six.moves.urllib.parse import urlsplit
2526
from google.cloud.storage.constants import _DEFAULT_TIMEOUT
2627

2728

@@ -491,3 +492,23 @@ def _raise_if_more_than_one_set(**kwargs):
491492
)
492493

493494
raise ValueError(msg)
495+
496+
497+
def _bucket_bound_hostname_url(host, scheme=None):
498+
"""Helper to build bucket bound hostname URL.
499+
500+
:type host: str
501+
:param host: Host name.
502+
503+
:type scheme: str
504+
:param scheme: (Optional) Web scheme. If passed, use it
505+
as a scheme in the result URL.
506+
507+
:rtype: str
508+
:returns: A bucket bound hostname URL.
509+
"""
510+
url_parts = urlsplit(host)
511+
if url_parts.scheme and url_parts.netloc:
512+
return host
513+
514+
return "{scheme}://{host}/".format(scheme=scheme, host=host)

google/cloud/storage/blob.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
from google.cloud.storage._helpers import _add_generation_match_parameters
5858
from google.cloud.storage._helpers import _PropertyMixin
5959
from google.cloud.storage._helpers import _scalar_property
60+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
6061
from google.cloud.storage._helpers import _convert_to_timestamp
6162
from google.cloud.storage._helpers import _raise_if_more_than_one_set
6263
from google.cloud.storage._signing import generate_signed_url_v2
@@ -516,12 +517,9 @@ def generate_signed_url(
516517
bucket_name=self.bucket.name
517518
)
518519
elif bucket_bound_hostname:
519-
if ":" in bucket_bound_hostname:
520-
api_access_endpoint = bucket_bound_hostname
521-
else:
522-
api_access_endpoint = "{scheme}://{bucket_bound_hostname}".format(
523-
scheme=scheme, bucket_bound_hostname=bucket_bound_hostname
524-
)
520+
api_access_endpoint = _bucket_bound_hostname_url(
521+
bucket_bound_hostname, scheme
522+
)
525523
else:
526524
resource = "/{bucket_name}/{quoted_name}".format(
527525
bucket_name=self.bucket.name, quoted_name=quoted_name

google/cloud/storage/bucket.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from google.cloud.storage._helpers import _validate_name
3939
from google.cloud.storage._signing import generate_signed_url_v2
4040
from google.cloud.storage._signing import generate_signed_url_v4
41+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
4142
from google.cloud.storage.acl import BucketACL
4243
from google.cloud.storage.acl import DefaultObjectACL
4344
from google.cloud.storage.blob import Blob
@@ -2861,12 +2862,9 @@ def generate_signed_url(
28612862
bucket_name=self.name
28622863
)
28632864
elif bucket_bound_hostname:
2864-
if ":" in bucket_bound_hostname:
2865-
api_access_endpoint = bucket_bound_hostname
2866-
else:
2867-
api_access_endpoint = "{scheme}://{bucket_bound_hostname}".format(
2868-
scheme=scheme, bucket_bound_hostname=bucket_bound_hostname
2869-
)
2865+
api_access_endpoint = _bucket_bound_hostname_url(
2866+
bucket_bound_hostname, scheme
2867+
)
28702868
else:
28712869
resource = "/{bucket_name}".format(bucket_name=self.name)
28722870

google/cloud/storage/client.py

+2-8
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,
@@ -1079,15 +1080,8 @@ def generate_signed_post_policy_v4(
10791080
# designate URL
10801081
if virtual_hosted_style:
10811082
url = "https://{}.storage.googleapis.com/".format(bucket_name)
1082-
10831083
elif bucket_bound_hostname:
1084-
if ":" in bucket_bound_hostname: # URL includes scheme
1085-
url = bucket_bound_hostname
1086-
1087-
else: # scheme is given separately
1088-
url = "{scheme}://{host}/".format(
1089-
scheme=scheme, host=bucket_bound_hostname
1090-
)
1084+
url = _bucket_bound_hostname_url(bucket_bound_hostname, scheme)
10911085
else:
10921086
url = "https://storage.googleapis.com/{}/".format(bucket_name)
10931087

tests/unit/test__helpers.py

+18
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,24 @@ def test_add_generation_match_parameters_tuple(self):
525525
)
526526

527527

528+
class Test__bucket_bound_hostname_url(unittest.TestCase):
529+
def _call_fut(self, **args):
530+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
531+
532+
return _bucket_bound_hostname_url(**args)
533+
534+
def test_full_hostname(self):
535+
HOST = "scheme://domain.tcl/"
536+
self.assertEqual(self._call_fut(host=HOST), HOST)
537+
538+
def test_hostname_and_scheme(self):
539+
HOST = "domain.tcl"
540+
SCHEME = "scheme"
541+
EXPECTED_URL = SCHEME + "://" + HOST + "/"
542+
543+
self.assertEqual(self._call_fut(host=HOST, scheme=SCHEME), EXPECTED_URL)
544+
545+
528546
class _Connection(object):
529547
def __init__(self, *responses):
530548
self._responses = responses

tests/unit/test_blob.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ def _generate_signed_url_helper(
405405
):
406406
from six.moves.urllib import parse
407407
from google.cloud._helpers import UTC
408+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
408409
from google.cloud.storage.blob import _API_ACCESS_ENDPOINT
409410
from google.cloud.storage.blob import _get_encryption_headers
410411

@@ -464,12 +465,9 @@ def _generate_signed_url_helper(
464465
bucket.name
465466
)
466467
elif bucket_bound_hostname:
467-
if ":" in bucket_bound_hostname:
468-
expected_api_access_endpoint = bucket_bound_hostname
469-
else:
470-
expected_api_access_endpoint = "{scheme}://{bucket_bound_hostname}".format(
471-
scheme=scheme, bucket_bound_hostname=bucket_bound_hostname
472-
)
468+
expected_api_access_endpoint = _bucket_bound_hostname_url(
469+
bucket_bound_hostname, scheme
470+
)
473471
else:
474472
expected_api_access_endpoint = api_access_endpoint
475473
expected_resource = "/{}/{}".format(bucket.name, quoted_name)

tests/unit/test_bucket.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -2990,6 +2990,7 @@ def _generate_signed_url_helper(
29902990
):
29912991
from six.moves.urllib import parse
29922992
from google.cloud._helpers import UTC
2993+
from google.cloud.storage._helpers import _bucket_bound_hostname_url
29932994
from google.cloud.storage.blob import _API_ACCESS_ENDPOINT
29942995

29952996
api_access_endpoint = api_access_endpoint or _API_ACCESS_ENDPOINT
@@ -3037,12 +3038,9 @@ def _generate_signed_url_helper(
30373038
bucket_name
30383039
)
30393040
elif bucket_bound_hostname:
3040-
if ":" in bucket_bound_hostname:
3041-
expected_api_access_endpoint = bucket_bound_hostname
3042-
else:
3043-
expected_api_access_endpoint = "{scheme}://{bucket_bound_hostname}".format(
3044-
scheme=scheme, bucket_bound_hostname=bucket_bound_hostname
3045-
)
3041+
expected_api_access_endpoint = _bucket_bound_hostname_url(
3042+
bucket_bound_hostname, scheme
3043+
)
30463044
else:
30473045
expected_api_access_endpoint = api_access_endpoint
30483046
expected_resource = "/{}".format(parse.quote(bucket_name))

0 commit comments

Comments
 (0)