Skip to content

Commit 6152ab4

Browse files
fix(storage): anonymous credentials for private bucket (#107)
* fix(storage): anonymous credentials for private bucket * fix(storage): use API_BASE_URL for hostname * fix(storage): nit * fix(storage): fix system test * fix(storage): revert changes Co-authored-by: Frank Natividad <[email protected]>
1 parent 69b2c45 commit 6152ab4

File tree

3 files changed

+50
-25
lines changed

3 files changed

+50
-25
lines changed

google/cloud/storage/blob.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
from google.cloud._helpers import _rfc3339_to_datetime
5555
from google.cloud._helpers import _to_bytes
5656
from google.cloud.exceptions import NotFound
57-
from google.cloud.storage._helpers import _get_storage_host
5857
from google.cloud.storage._helpers import _PropertyMixin
5958
from google.cloud.storage._helpers import _scalar_property
6059
from google.cloud.storage._helpers import _convert_to_timestamp
@@ -70,12 +69,11 @@
7069
from google.cloud.storage.constants import REGIONAL_LEGACY_STORAGE_CLASS
7170
from google.cloud.storage.constants import STANDARD_STORAGE_CLASS
7271

73-
_STORAGE_HOST = _get_storage_host()
7472

7573
_API_ACCESS_ENDPOINT = "https://storage.googleapis.com"
7674
_DEFAULT_CONTENT_TYPE = u"application/octet-stream"
77-
_DOWNLOAD_URL_TEMPLATE = _STORAGE_HOST + u"/download/storage/v1{path}?alt=media"
78-
_BASE_UPLOAD_TEMPLATE = _STORAGE_HOST + u"/upload/storage/v1{bucket_path}/o?uploadType="
75+
_DOWNLOAD_URL_TEMPLATE = u"{hostname}/download/storage/v1{path}?alt=media"
76+
_BASE_UPLOAD_TEMPLATE = u"{hostname}/upload/storage/v1{bucket_path}/o?uploadType="
7977
_MULTIPART_URL_TEMPLATE = _BASE_UPLOAD_TEMPLATE + u"multipart"
8078
_RESUMABLE_URL_TEMPLATE = _BASE_UPLOAD_TEMPLATE + u"resumable"
8179
# NOTE: "acl" is also writeable but we defer ACL management to
@@ -650,19 +648,24 @@ def _get_transport(self, client):
650648
client = self._require_client(client)
651649
return client._http
652650

653-
def _get_download_url(self):
651+
def _get_download_url(self, client):
654652
"""Get the download URL for the current blob.
655653
656654
If the ``media_link`` has been loaded, it will be used, otherwise
657655
the URL will be constructed from the current blob's path (and possibly
658656
generation) to avoid a round trip.
659657
658+
:type client: :class:`~google.cloud.storage.client.Client`
659+
:param client: The client to use.
660+
660661
:rtype: str
661662
:returns: The download URL for the current blob.
662663
"""
663664
name_value_pairs = []
664665
if self.media_link is None:
665-
base_url = _DOWNLOAD_URL_TEMPLATE.format(path=self.path)
666+
base_url = _DOWNLOAD_URL_TEMPLATE.format(
667+
hostname=client._connection.API_BASE_URL, path=self.path
668+
)
666669
if self.generation is not None:
667670
name_value_pairs.append(("generation", "{:d}".format(self.generation)))
668671
else:
@@ -790,7 +793,8 @@ def download_to_file(
790793
791794
:raises: :class:`google.cloud.exceptions.NotFound`
792795
"""
793-
download_url = self._get_download_url()
796+
client = self._require_client(client)
797+
download_url = self._get_download_url(client)
794798
headers = _get_encryption_headers(self._encryption_key)
795799
headers["accept-encoding"] = "gzip"
796800

@@ -1055,7 +1059,9 @@ def _do_multipart_upload(
10551059
info = self._get_upload_arguments(content_type)
10561060
headers, object_metadata, content_type = info
10571061

1058-
base_url = _MULTIPART_URL_TEMPLATE.format(bucket_path=self.bucket.path)
1062+
base_url = _MULTIPART_URL_TEMPLATE.format(
1063+
hostname=self.client._connection.API_BASE_URL, bucket_path=self.bucket.path
1064+
)
10591065
name_value_pairs = []
10601066

10611067
if self.user_project is not None:
@@ -1190,7 +1196,9 @@ def _initiate_resumable_upload(
11901196
if extra_headers is not None:
11911197
headers.update(extra_headers)
11921198

1193-
base_url = _RESUMABLE_URL_TEMPLATE.format(bucket_path=self.bucket.path)
1199+
base_url = _RESUMABLE_URL_TEMPLATE.format(
1200+
hostname=self.client._connection.API_BASE_URL, bucket_path=self.bucket.path
1201+
)
11941202
name_value_pairs = []
11951203

11961204
if self.user_project is not None:

tests/unit/test_blob.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,10 @@ def test__get_download_url_with_media_link(self):
751751
# Set the media link on the blob
752752
blob._properties["mediaLink"] = media_link
753753

754-
download_url = blob._get_download_url()
754+
client = mock.Mock(_connection=_Connection)
755+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
756+
download_url = blob._get_download_url(client)
757+
755758
self.assertEqual(download_url, media_link)
756759

757760
def test__get_download_url_with_media_link_w_user_project(self):
@@ -763,7 +766,10 @@ def test__get_download_url_with_media_link_w_user_project(self):
763766
# Set the media link on the blob
764767
blob._properties["mediaLink"] = media_link
765768

766-
download_url = blob._get_download_url()
769+
client = mock.Mock(_connection=_Connection)
770+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
771+
download_url = blob._get_download_url(client)
772+
767773
self.assertEqual(
768774
download_url, "{}?userProject={}".format(media_link, user_project)
769775
)
@@ -774,7 +780,9 @@ def test__get_download_url_on_the_fly(self):
774780
blob = self._make_one(blob_name, bucket=bucket)
775781

776782
self.assertIsNone(blob.media_link)
777-
download_url = blob._get_download_url()
783+
client = mock.Mock(_connection=_Connection)
784+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
785+
download_url = blob._get_download_url(client)
778786
expected_url = (
779787
"https://storage.googleapis.com/download/storage/v1/b/"
780788
"buhkit/o/bzzz-fly.txt?alt=media"
@@ -790,7 +798,9 @@ def test__get_download_url_on_the_fly_with_generation(self):
790798
blob._properties["generation"] = str(generation)
791799

792800
self.assertIsNone(blob.media_link)
793-
download_url = blob._get_download_url()
801+
client = mock.Mock(_connection=_Connection)
802+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
803+
download_url = blob._get_download_url(client)
794804
expected_url = (
795805
"https://storage.googleapis.com/download/storage/v1/b/"
796806
"fictional/o/pretend.txt?alt=media&generation=1493058489532987"
@@ -804,7 +814,9 @@ def test__get_download_url_on_the_fly_with_user_project(self):
804814
blob = self._make_one(blob_name, bucket=bucket)
805815

806816
self.assertIsNone(blob.media_link)
807-
download_url = blob._get_download_url()
817+
client = mock.Mock(_connection=_Connection)
818+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
819+
download_url = blob._get_download_url(client)
808820
expected_url = (
809821
"https://storage.googleapis.com/download/storage/v1/b/"
810822
"fictional/o/pretend.txt?alt=media&userProject={}".format(user_project)
@@ -823,7 +835,9 @@ def test__get_download_url_on_the_fly_with_kms_key_name(self):
823835
blob = self._make_one(blob_name, bucket=bucket, kms_key_name=kms_resource)
824836

825837
self.assertIsNone(blob.media_link)
826-
download_url = blob._get_download_url()
838+
client = mock.Mock(_connection=_Connection)
839+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
840+
download_url = blob._get_download_url(client)
827841
expected_url = (
828842
"https://storage.googleapis.com/download/storage/v1/b/"
829843
"buhkit/o/bzzz-fly.txt?alt=media"
@@ -1003,7 +1017,8 @@ def test_download_to_file_with_failure(self):
10031017

10041018
def test_download_to_file_wo_media_link(self):
10051019
blob_name = "blob-name"
1006-
client = mock.Mock(spec=[u"_http"])
1020+
client = mock.Mock(_connection=_Connection, spec=[u"_http"])
1021+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
10071022
bucket = _Bucket(client)
10081023
blob = self._make_one(blob_name, bucket=bucket)
10091024
blob._do_download = mock.Mock()
@@ -1319,7 +1334,8 @@ def _do_multipart_success(
13191334
transport = self._mock_transport(http_client.OK, {})
13201335

13211336
# Create some mock arguments.
1322-
client = mock.Mock(_http=transport, spec=["_http"])
1337+
client = mock.Mock(_http=transport, _connection=_Connection, spec=["_http"])
1338+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
13231339
data = b"data here hear hier"
13241340
stream = io.BytesIO(data)
13251341
content_type = u"application/xml"
@@ -1485,7 +1501,8 @@ def _initiate_resumable_helper(
14851501
transport = self._mock_transport(http_client.OK, response_headers)
14861502

14871503
# Create some mock arguments and call the method under test.
1488-
client = mock.Mock(_http=transport, spec=[u"_http"])
1504+
client = mock.Mock(_http=transport, _connection=_Connection, spec=[u"_http"])
1505+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
14891506
data = b"hello hallo halo hi-low"
14901507
stream = io.BytesIO(data)
14911508
content_type = u"text/plain"
@@ -1772,7 +1789,8 @@ def _do_resumable_helper(
17721789
)
17731790

17741791
# Create some mock arguments and call the method under test.
1775-
client = mock.Mock(_http=transport, spec=["_http"])
1792+
client = mock.Mock(_http=transport, _connection=_Connection, spec=["_http"])
1793+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
17761794
stream = io.BytesIO(data)
17771795
content_type = u"text/html"
17781796
response = blob._do_resumable_upload(
@@ -2114,7 +2132,8 @@ def _create_resumable_upload_session_helper(self, origin=None, side_effect=None)
21142132
# Create some mock arguments and call the method under test.
21152133
content_type = u"text/plain"
21162134
size = 10000
2117-
client = mock.Mock(_http=transport, spec=[u"_http"])
2135+
client = mock.Mock(_http=transport, _connection=_Connection, spec=[u"_http"])
2136+
client._connection.API_BASE_URL = "https://storage.googleapis.com"
21182137
new_url = blob.create_resumable_upload_session(
21192138
content_type=content_type, size=size, origin=origin, client=client
21202139
)

tests/unit/test_client.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,16 @@ def test_ctor_w_empty_client_options(self):
137137
)
138138

139139
def test_ctor_w_client_options_dict(self):
140-
141140
PROJECT = "PROJECT"
142141
credentials = _make_credentials()
143-
client_options = {"api_endpoint": "https://www.foo-googleapis.com"}
142+
api_endpoint = "https://www.foo-googleapis.com"
143+
client_options = {"api_endpoint": api_endpoint}
144144

145145
client = self._make_one(
146146
project=PROJECT, credentials=credentials, client_options=client_options
147147
)
148148

149-
self.assertEqual(
150-
client._connection.API_BASE_URL, "https://www.foo-googleapis.com"
151-
)
149+
self.assertEqual(client._connection.API_BASE_URL, api_endpoint)
152150

153151
def test_ctor_w_client_options_object(self):
154152
from google.api_core.client_options import ClientOptions

0 commit comments

Comments
 (0)