Repository: gomods/athens
Pull request #1388 (2019-09-19 20:26:22)

proxy/actions/sumdb: copy Go behavior for pattern matching
This makes it so that if a user enters `github.com/company/*`, it will match against all modules and submodules of github.com/company such as `github.com/company/private` and `github.com/company/private/other` 

fixes https://github.com/gomods/athens/issues/1386


robjloranger: Awesome @marwan-at-work this looks great, I tried testing but am getting a timeout fetching git.apache.org/thrift so can't verify using tests. Any idea what that's about?
marwan-at-work: @robjloranger can you try running again with GOPROXY=proxy.golang.org? 
robjloranger: @marwan-at-work using the non-docker with `GOPROXY` set I got:
```
go: finding git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999
can't load package: package github.com/gomods/athens: unknown import path "github.com/gomods/athens": cannot find module providing package github.com/gomods/athens
```

and with the docker based tests I get:
```
testunit_1  | go: git.apache.org/thrift.git@v0.0.0-20180902110319-2566ecd5d999: git fetch -f origin refs/heads/*:refs/heads/* refs/tags/*:refs/tags/* in /go/pkg/mod/cache/vcs/83dba939f95a790e497d565fc4418400145a1a514f955fa052f662d56e920c3e: exit status 128:
testunit_1  | 	fatal: unable to access 'https://git.apache.org/thrift.git/': Failed to connect to git.apache.org port 443: Connection timed out
testunit_1  | go: error loading module requirements
```

I am running 1.13 if that matters.
robjloranger: weird, now it's passing if I don't specify the test by name but `./...` with `GOPROXY` set.

cool

Patch:
diff --git a/cmd/proxy/actions/sumdb.go b/cmd/proxy/actions/sumdb.go
index 95ca49ae..6fdd0e11 100644
--- a/cmd/proxy/actions/sumdb.go
+++ b/cmd/proxy/actions/sumdb.go
@@ -25,7 +25,7 @@ func noSumWrapper(h http.Handler, host string, patterns []string) http.Handler {
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		if strings.HasPrefix(r.URL.Path, "/lookup/") {
 			for _, p := range patterns {
-				if isMatch, err := path.Match(p, r.URL.Path[len("/lookup/"):]); err == nil && isMatch {
+				if matchesPattern(p, r.URL.Path[len("/lookup/"):]) {
 					w.WriteHeader(http.StatusForbidden)
 					return
 				}
@@ -34,3 +34,29 @@ func noSumWrapper(h http.Handler, host string, patterns []string) http.Handler {
 		h.ServeHTTP(w, r)
 	})
 }
+
+// matchesPattern is adopted from
+// https://github.com/golang/go/blob/a11644a26557ea436d456f005f39f4e01902bafe/src/cmd/go/internal/str/path.go#L58
+// this function matches based on path prefixes and
+// tries to keep the same behavior as GONOSUMDB and friends
+func matchesPattern(pattern, target string) bool {
+	n := strings.Count(pattern, "/")
+	prefix := target
+	for i := 0; i < len(target); i++ {
+		if target[i] == '/' {
+			if n == 0 {
+				prefix = target[:i]
+				break
+			}
+			n--
+		}
+	}
+	if n > 0 {
+		return false
+	}
+	matched, _ := path.Match(pattern, prefix)
+	if matched {
+		return true
+	}
+	return false
+}


Test patch:
diff --git a/cmd/proxy/actions/sumdb_test.go b/cmd/proxy/actions/sumdb_test.go
index e8239cdf..7b668718 100644
--- a/cmd/proxy/actions/sumdb_test.go
+++ b/cmd/proxy/actions/sumdb_test.go
@@ -61,6 +61,30 @@ var noSumTestCases = []struct {
 		"github.com/private/repo@v0.0.1",
 		http.StatusForbidden,
 	},
+	{
+		"multi slash star",
+		[]string{"github.com/private/*"},
+		"github.com/private/repo/sub@v0.0.1",
+		http.StatusForbidden,
+	},
+	{
+		"multi star",
+		[]string{"github.com/*/*"},
+		"github.com/private/repo@v0.0.1",
+		http.StatusForbidden,
+	},
+	{
+		"multi star ok",
+		[]string{"github.com/private/*/*"},
+		"github.com/private/repo@v0.0.1",
+		http.StatusOK,
+	},
+	{
+		"multi star forbidden",
+		[]string{"github.com/private/*/*"},
+		"github.com/private/repo/sub@v0.0.1",
+		http.StatusForbidden,
+	},
 	{
 		"any version",
 		[]string{"github.com/private/repo*"},