5757from google .cloud .storage ._helpers import _raise_if_more_than_one_set
5858from google .cloud .storage ._helpers import _api_core_retry_to_resumable_media_retry
5959from google .cloud .storage ._helpers import _get_default_headers
60+ from google .cloud .storage ._helpers import _get_default_storage_base_url
6061from google .cloud .storage ._signing import generate_signed_url_v2
6162from google .cloud .storage ._signing import generate_signed_url_v4
6263from google .cloud .storage ._helpers import _NUM_RETRIES_MESSAGE
63- from google .cloud .storage ._helpers import _DEFAULT_STORAGE_HOST
6464from google .cloud .storage ._helpers import _API_VERSION
65+ from google .cloud .storage ._helpers import _virtual_hosted_style_base_url
6566from google .cloud .storage .acl import ACL
6667from google .cloud .storage .acl import ObjectACL
6768from google .cloud .storage .constants import _DEFAULT_TIMEOUT
8081from google .cloud .storage .fileio import BlobWriter
8182
8283
83- _API_ACCESS_ENDPOINT = _DEFAULT_STORAGE_HOST
8484_DEFAULT_CONTENT_TYPE = "application/octet-stream"
8585_DOWNLOAD_URL_TEMPLATE = "{hostname}/download/storage/{api_version}{path}?alt=media"
8686_BASE_UPLOAD_TEMPLATE = (
@@ -376,8 +376,12 @@ def public_url(self):
376376 :rtype: `string`
377377 :returns: The public URL for this blob.
378378 """
379+ if self .client :
380+ endpoint = self .client .api_endpoint
381+ else :
382+ endpoint = _get_default_storage_base_url ()
379383 return "{storage_base_url}/{bucket_name}/{quoted_name}" .format (
380- storage_base_url = _API_ACCESS_ENDPOINT ,
384+ storage_base_url = endpoint ,
381385 bucket_name = self .bucket .name ,
382386 quoted_name = _quote (self .name , safe = b"/~" ),
383387 )
@@ -416,7 +420,7 @@ def from_string(cls, uri, client=None):
416420 def generate_signed_url (
417421 self ,
418422 expiration = None ,
419- api_access_endpoint = _API_ACCESS_ENDPOINT ,
423+ api_access_endpoint = None ,
420424 method = "GET" ,
421425 content_md5 = None ,
422426 content_type = None ,
@@ -464,7 +468,9 @@ def generate_signed_url(
464468 assumed to be ``UTC``.
465469
466470 :type api_access_endpoint: str
467- :param api_access_endpoint: (Optional) URI base.
471+ :param api_access_endpoint: (Optional) URI base, for instance
472+ "https://storage.googleapis.com". If not specified, the client's
473+ api_endpoint will be used. Incompatible with bucket_bound_hostname.
468474
469475 :type method: str
470476 :param method: The HTTP verb that will be used when requesting the URL.
@@ -537,21 +543,22 @@ def generate_signed_url(
537543 :param virtual_hosted_style:
538544 (Optional) If true, then construct the URL relative the bucket's
539545 virtual hostname, e.g., '<bucket-name>.storage.googleapis.com'.
546+ Incompatible with bucket_bound_hostname.
540547
541548 :type bucket_bound_hostname: str
542549 :param bucket_bound_hostname:
543- (Optional) If passed, then construct the URL relative to the
544- bucket-bound hostname. Value can be a bare or with scheme, e.g.,
545- 'example.com' or 'http://example.com'. See:
546- https://cloud.google.com/storage/docs/request-endpoints#cname
550+ (Optional) If passed, then construct the URL relative to the bucket-bound hostname.
551+ Value can be a bare or with scheme, e.g., 'example.com' or 'http://example.com'.
552+ Incompatible with api_access_endpoint and virtual_hosted_style.
553+ See: https://cloud.google.com/storage/docs/request-endpoints#cname
547554
548555 :type scheme: str
549556 :param scheme:
550557 (Optional) If ``bucket_bound_hostname`` is passed as a bare
551558 hostname, use this value as the scheme. ``https`` will work only
552559 when using a CDN. Defaults to ``"http"``.
553560
554- :raises: :exc:`ValueError` when version is invalid.
561+ :raises: :exc:`ValueError` when version is invalid or mutually exclusive arguments are used .
555562 :raises: :exc:`TypeError` when expiration is not a valid type.
556563 :raises: :exc:`AttributeError` if credentials is not an instance
557564 of :class:`google.auth.credentials.Signing`.
@@ -565,25 +572,38 @@ def generate_signed_url(
565572 elif version not in ("v2" , "v4" ):
566573 raise ValueError ("'version' must be either 'v2' or 'v4'" )
567574
575+ if (
576+ api_access_endpoint is not None or virtual_hosted_style
577+ ) and bucket_bound_hostname :
578+ raise ValueError (
579+ "The bucket_bound_hostname argument is not compatible with "
580+ "either api_access_endpoint or virtual_hosted_style."
581+ )
582+
583+ if api_access_endpoint is None :
584+ client = self ._require_client (client )
585+ api_access_endpoint = client .api_endpoint
586+
568587 quoted_name = _quote (self .name , safe = b"/~" )
569588
570589 # If you are on Google Compute Engine, you can't generate a signed URL
571590 # using GCE service account.
572591 # See https://github.com/googleapis/google-auth-library-python/issues/50
573592 if virtual_hosted_style :
574- api_access_endpoint = f"https://{ self .bucket .name } .storage.googleapis.com"
593+ api_access_endpoint = _virtual_hosted_style_base_url (
594+ api_access_endpoint , self .bucket .name
595+ )
596+ resource = f"/{ quoted_name } "
575597 elif bucket_bound_hostname :
576598 api_access_endpoint = _bucket_bound_hostname_url (
577599 bucket_bound_hostname , scheme
578600 )
601+ resource = f"/{ quoted_name } "
579602 else :
580603 resource = f"/{ self .bucket .name } /{ quoted_name } "
581604
582- if virtual_hosted_style or bucket_bound_hostname :
583- resource = f"/{ quoted_name } "
584-
585605 if credentials is None :
586- client = self ._require_client (client )
606+ client = self ._require_client (client ) # May be redundant, but that's ok.
587607 credentials = client ._credentials
588608
589609 if version == "v2" :
0 commit comments