@@ -491,6 +491,23 @@ def _fix_up_method_description(method_desc, root_desc):
491491 return path_url , http_method , method_id , accept , max_size , media_path_url
492492
493493
494+ def _urljoin (base , url ):
495+ """Custom urljoin replacement supporting : before / in url."""
496+ # In general, it's unsafe to simply join base and url. However, for
497+ # the case of discovery documents, we know:
498+ # * base will never contain params, query, or fragment
499+ # * url will never contain a scheme or net_loc.
500+ # In general, this means we can safely join on /; we just need to
501+ # ensure we end up with precisely one / joining base and url. The
502+ # exception here is the case of media uploads, where url will be an
503+ # absolute url.
504+ if url .startswith ('http://' ) or url .startswith ('https://' ):
505+ return urlparse .urljoin (base , url )
506+ new_base = base if base .endswith ('/' ) else base + '/'
507+ new_url = url [1 :] if url .startswith ('/' ) else url
508+ return new_base + new_url
509+
510+
494511# TODO(dhermes): Convert this class to ResourceMethod and make it callable
495512class ResourceMethodParameters (object ):
496513 """Represents the parameters associated with a method.
@@ -671,7 +688,7 @@ def method(self, **kwargs):
671688 actual_path_params , actual_query_params , body_value )
672689
673690 expanded_url = uritemplate .expand (pathUrl , params )
674- url = urlparse . urljoin (self ._baseUrl , expanded_url + query )
691+ url = _urljoin (self ._baseUrl , expanded_url + query )
675692
676693 resumable = None
677694 multipart_boundary = ''
@@ -697,7 +714,7 @@ def method(self, **kwargs):
697714
698715 # Use the media path uri for media uploads
699716 expanded_url = uritemplate .expand (mediaPathUrl , params )
700- url = urlparse . urljoin (self ._baseUrl , expanded_url + query )
717+ url = _urljoin (self ._baseUrl , expanded_url + query )
701718 if media_upload .resumable ():
702719 url = _add_query_parameter (url , 'uploadType' , 'resumable' )
703720
0 commit comments