diff --git a/main_test.go b/main_test.go index c41224d92a48b216fba02f1b4d8e1f4d120ad34d..15a4cb28c6305dbd12d6605dcbc1321d499a9bfc 100644 --- a/main_test.go +++ b/main_test.go @@ -12,6 +12,7 @@ import ( "os/exec" "path" "regexp" + "strings" "testing" "time" ) @@ -196,6 +197,29 @@ func TestAllowedApiDownloadZip(t *testing.T) { runOrFail(t, extractCmd) } +func TestAllowedApiDownloadZipWithSlash(t *testing.T) { + prepareDownloadDir(t) + + // Prepare test server and backend + archiveName := "foobar.zip" + ts := testAuthServer(nil, 200, archiveOkBody(t, archiveName)) + defer ts.Close() + ws := startWorkhorseServer(ts.URL) + defer ws.Close() + + // Use foo%2Fbar instead of a numeric ID + downloadCmd := exec.Command("curl", "-J", "-O", fmt.Sprintf("%s/api/v3/projects/foo%%2Fbar/repository/archive.zip", ws.URL)) + if !strings.Contains(downloadCmd.Args[3], `projects/foo%2Fbar/repository`) { + t.Fatalf("Cannot find percent-2F: %v", downloadCmd.Args) + } + downloadCmd.Dir = scratchDir + runOrFail(t, downloadCmd) + + extractCmd := exec.Command("unzip", archiveName) + extractCmd.Dir = scratchDir + runOrFail(t, extractCmd) +} + func TestDownloadCacheHit(t *testing.T) { prepareDownloadDir(t) diff --git a/upstream.go b/upstream.go index bcfbc8a34461e4a698b80cde4bb18db745dc654c..4f100165c4ce5bc642012d1c8cfa5e5ea02e66ae 100644 --- a/upstream.go +++ b/upstream.go @@ -107,7 +107,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) { } // Check URL Root - URIPath := cleanURIPath(r.URL.Path) + URIPath := cleanURIPath(r.URL.EscapedPath()) if !strings.HasPrefix(URIPath, u.relativeURLRoot) && URIPath+"/" != u.relativeURLRoot { httpError(&w, r, fmt.Sprintf("Not found %q", URIPath), http.StatusNotFound) return