@@ -117,6 +117,39 @@ Authorization: Bearer RANDOM-TOKEN
117117# We can't disable timeouts on Bazel, but we can set them to large values. 
118118_GO_REPOSITORY_TIMEOUT  =  86400 
119119
120+ def  _escape_go_module_path (module_path ):
121+     """Escapes a Go module path according to the Go proxy protocol.""" 
122+     result  =  "" 
123+     for  c  in  module_path .elems ():
124+         if  "A"  <=  c  and  c  <=  "Z" :
125+             result  +=  "!"  +  c .lower ()
126+         else :
127+             result  +=  c 
128+     return  result 
129+ 
130+ def  _get_goproxy_url (env ):
131+     """Return proxy URL to be used for module_path, or None if no proxy will be used.""" 
132+     goproxy  =  env .get ("GOPROXY" , "" )
133+     goprivate  =  env .get ("GOPRIVATE" , "" )
134+     gonoproxy  =  env .get ("GONOPROXY" , "" )
135+ 
136+     # TODO(zbarsky): In the future, we could try to handle some subset of downloads even if GONOPROXY/GOPRIVATE are set. 
137+     # Doing this correctly requires care, as the syntax is powerful, and we don't want to get it wrong and request from the proxy. 
138+     if  goproxy  ==  "off"  or  goprivate  or  gonoproxy :
139+         return  None 
140+ 
141+     if  not  goproxy :
142+         return  "https://proxy.golang.org" 
143+ 
144+     idx  =  goproxy .find ("," )
145+     if  idx  !=  - 1 :
146+         goproxy  =  goproxy [:idx ]
147+ 
148+     if  goproxy  ==  "direct" :
149+         return  None 
150+ 
151+     return  goproxy 
152+ 
120153def  _go_repository_impl (ctx ):
121154    # TODO(#549): vcs repositories are not cached and still need to be fetched. 
122155    # Download the repository or module. 
@@ -137,6 +170,7 @@ def _go_repository_impl(ctx):
137170        gazelle_path  =  ctx .path (Label (_gazelle ))
138171        watch (ctx , gazelle_path )
139172
173+     can_use_direct_download  =  False 
140174    reproducible  =  False 
141175    if  ctx .attr .local_path :
142176        if  hasattr (ctx , "watch_tree" ):
@@ -204,6 +238,7 @@ def _go_repository_impl(ctx):
204238            else :
205239                fail ("if version is specified, sum must also be" )
206240        reproducible  =  True 
241+         can_use_direct_download  =  True 
207242
208243        fetch_path  =  ctx .attr .replace  if  ctx .attr .replace  else  ctx .attr .importpath 
209244        fetch_repo_args  =  [
@@ -286,6 +321,30 @@ def _go_repository_impl(ctx):
286321    # Override external GO111MODULE, because it is needed by module mode, no-op in repository mode 
287322    fetch_repo_env ["GO111MODULE" ] =  "on" 
288323
324+     if  can_use_direct_download :
325+         proxy_url  =  _get_goproxy_url (env )
326+         if  proxy_url :
327+             module  =  ctx .attr .replace  if  ctx .attr .replace  else  ctx .attr .importpath 
328+             url  =  "%s/%s/@v/%s.zip"  %  (
329+                 proxy_url ,
330+                 _escape_go_module_path (module ),
331+                 ctx .attr .version ,
332+             )
333+             result  =  ctx .download_and_extract (
334+                 url  =  url ,
335+                 sha256  =  ctx .attr .sha256 ,
336+                 canonical_id  =  url ,
337+                 stripPrefix  =  module  +  "@"  +  ctx .attr .version ,
338+                 type  =  ctx .attr .type ,
339+                 auth  =  use_netrc (read_user_netrc (ctx ), ctx .attr .urls , ctx .attr .auth_patterns ),
340+                 allow_fail  =  True ,
341+             )
342+             if  result .success :
343+                 # All we need to do now is verify the sum! 
344+                 fetch_repo_args  =  ["-no-fetch" ] +  fetch_repo_args 
345+             # If we did not succeed, fallback to using the Go tooling to fetch the module. This matches 
346+             # what would happen normally (especially since we only tried the first entry in GOPROXY). 
347+ 
289348    result  =  env_execute (
290349        ctx ,
291350        [fetch_repo ] +  fetch_repo_args ,
0 commit comments