Skip to content

Commit

Permalink
bug-1905455: Enable anonymous access to GCS buckets.
Browse files Browse the repository at this point in the history
  • Loading branch information
smarnach committed Jul 11, 2024
1 parent 00f092b commit 136300e
Showing 1 changed file with 19 additions and 14 deletions.
33 changes: 19 additions & 14 deletions tecken/ext/gcs/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
from urllib.parse import quote, urlparse

from django.conf import settings

from google.api_core.client_options import ClientOptions
from google.api_core.exceptions import ClientError, NotFound
from google.api_core.exceptions import ClientError
from google.cloud import storage
from requests.exceptions import RequestException

from tecken.librequests import session_with_retries
from tecken.libstorage import ObjectMetadata, StorageBackend, StorageError


Expand Down Expand Up @@ -52,13 +53,7 @@ def _get_client(self) -> storage.Client:

def _get_bucket(self) -> storage.Bucket:
"""Return a thread-local low-level storage bucket client."""
if not hasattr(self.clients, "bucket"):
client = self._get_client()
try:
self.clients.bucket = client.get_bucket(self.name, timeout=self.timeout)
except NotFound as exc:
raise StorageError(self) from exc
return self.clients.bucket
return self._get_client().bucket(self.name)

def exists(self) -> bool:
"""Check that this storage exists.
Expand All @@ -67,13 +62,23 @@ def exists(self) -> bool:
:raises StorageError: an unexpected backend-specific error was raised
"""
session = session_with_retries()
if self.endpoint_url.startswith("http://gcs-emulator"):
# NOTE(smarnach): The GCS emulator does not support HEAD requests. Moreover, the
# simpler public endpoint used below will throw 500s if the bucket doesn't exists,
# tripping up the retry behaviour. We can't use this endpoint for Google's API,
# since it requires authentication, and we want to be able to detect the existence
# of public buckets anonymously (bug 1905455).
method = "GET"
url = f"{self.endpoint_url}/storage/v1/b/{self.name}"
else:
method = "HEAD"
url = f"{self.endpoint_url}/{self.name}"
try:
self._get_bucket()
except StorageError:
return False
except ClientError as exc:
response = session.request(method, url)
except RequestException as exc:
raise StorageError(self) from exc
return True
return response.status_code == 200

def get_object_metadata(self, key: str) -> Optional[ObjectMetadata]:
"""Return object metadata for the object with the given key.
Expand Down

0 comments on commit 136300e

Please sign in to comment.