cmd/go/internal/web: don't follow an infinite number of redirects
We replaced http.DefaultClient with securityPreservingHTTPClient,
but we still need that too many redirects check. This issue introduced
by CL 156838.
We introduce a special path to test rediret requests in the script test
framework. You can specify the number of redirects in the path.
$GOPROXY/redirect/<count>/...
Redirect request sequence details(count=8):
request: $GOPROXY/mod/redirect/8/rsc.io/quote/@v/v1.2.0.mod
redirect: $GOPROXY/mod/redirect/7/rsc.io/quote/@v/v1.2.0.mod
redirect: $GOPROXY/mod/redirect/6/rsc.io/quote/@v/v1.2.0.mod
redirect: $GOPROXY/mod/redirect/5/rsc.io/quote/@v/v1.2.0.mod
redirect: $GOPROXY/mod/redirect/4/rsc.io/quote/@v/v1.2.0.mod
redirect: $GOPROXY/mod/redirect/3/rsc.io/quote/@v/v1.2.0.mod
redirect: $GOPROXY/mod/redirect/2/rsc.io/quote/@v/v1.2.0.mod
redirect: $GOPROXY/mod/redirect/1/rsc.io/quote/@v/v1.2.0.mod
the last: $GOPROXY/mod/rsc.io/quote/@v/v1.2.0.mod
Fixes #39482
Change-Id: I149a3702b2b616069baeef787b2e4b73afc93b0e
Reviewed-on: https://go-review.googlesource.com/c/go/+/237177
Run-TryBot: Baokun Lee <nototon@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
diff --git a/src/cmd/go/internal/web/http.go b/src/cmd/go/internal/web/http.go
index beb80c5..e050980 100644
--- a/src/cmd/go/internal/web/http.go
+++ b/src/cmd/go/internal/web/http.go
@@ -13,6 +13,7 @@
import (
"crypto/tls"
+ "errors"
"fmt"
"mime"
"net/http"
@@ -47,6 +48,13 @@
lastHop := via[len(via)-1].URL
return fmt.Errorf("redirected from secure URL %s to insecure URL %s", lastHop, req.URL)
}
+
+ // Go's http.DefaultClient allows 10 redirects before returning an error.
+ // The securityPreservingHTTPClient also uses this default policy to avoid
+ // Go command hangs.
+ if len(via) >= 10 {
+ return errors.New("stopped after 10 redirects")
+ }
return nil
},
}
diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go
index 8214488..2a4d293 100644
--- a/src/cmd/go/proxy_test.go
+++ b/src/cmd/go/proxy_test.go
@@ -174,6 +174,25 @@
return
}
+ // Request for $GOPROXY/redirect/<count>/... goes to redirects.
+ if strings.HasPrefix(path, "redirect/") {
+ path = path[len("redirect/"):]
+ if j := strings.Index(path, "/"); j >= 0 {
+ count, err := strconv.Atoi(path[:j])
+ if err != nil {
+ return
+ }
+
+ // The last redirect.
+ if count <= 1 {
+ http.Redirect(w, r, fmt.Sprintf("/mod/%s", path[j+1:]), 302)
+ return
+ }
+ http.Redirect(w, r, fmt.Sprintf("/mod/redirect/%d/%s", count-1, path[j+1:]), 302)
+ return
+ }
+ }
+
// Request for $GOPROXY/sumdb/<name>/supported
// is checking whether it's OK to access sumdb via the proxy.
if path == "sumdb/"+testSumDBName+"/supported" {
diff --git a/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt b/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt
new file mode 100644
index 0000000..9cbe0d2
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt
@@ -0,0 +1,10 @@
+env GO111MODULE=on
+env GOPROXYBASE=$GOPROXY
+env GOPROXY=$GOPROXYBASE/redirect/11
+env GOSUMDB=off
+
+! go get -d rsc.io/quote@v1.2.0
+stderr 'stopped after 10 redirects'
+
+env GOPROXY=$GOPROXYBASE/redirect/9
+go get -d rsc.io/quote@v1.2.0