diff --git a/download/proxy.go b/download/proxy.go index cc2afb7..3e96628 100644 --- a/download/proxy.go +++ b/download/proxy.go @@ -15,6 +15,7 @@ import ( const ( proxyLatestURL = "https://proxy.golang.org/%s/@latest" proxyZipURL = "https://proxy.golang.org/%s/@v/%s.zip" + proxyModURL = "https://proxy.golang.org/%s/@v/%s.mod" reposDir = "_repos/src" ) @@ -22,8 +23,46 @@ type moduleVersion struct { Version string } -// ProxyDownload downloads a package from proxy.golang.org -func ProxyDownload(path string) (string, error) { +// ModuleName gets the name of a module from the proxy +func ModuleName(path string) (string, error) { + lowerPath := strings.ToLower(path) + + ver, err := LatestVersion(path) + if err != nil { + return "", err + } + + u := fmt.Sprintf(proxyModURL, lowerPath, ver) + resp, err := http.Get(u) + if err != nil { + return "", err + } + + defer resp.Body.Close() + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("could not get latest module version from %s: %s", u, string(b)) + } + + sp := strings.Split(string(b), "\n") + if len(sp) == 0 { + return "", fmt.Errorf("empty go.mod") + } + + mn := strings.Fields(sp[0]) + if len(mn) != 2 { + return "", fmt.Errorf("invalid go.mod: %s", mn) + } + + return mn[1], nil +} + +// LatestVersion gets the latest module version from the proxy +func LatestVersion(path string) (string, error) { lowerPath := strings.ToLower(path) u := fmt.Sprintf(proxyLatestURL, lowerPath) resp, err := http.Get(u) @@ -45,7 +84,19 @@ func ProxyDownload(path string) (string, error) { return "", err } - resp, err = http.Get(fmt.Sprintf(proxyZipURL, lowerPath, mv.Version)) + return mv.Version, nil +} + +// ProxyDownload downloads a package from proxy.golang.org +func ProxyDownload(path string) (string, error) { + lowerPath := strings.ToLower(path) + + ver, err := LatestVersion(path) + if err != nil { + return "", err + } + + resp, err := http.Get(fmt.Sprintf(proxyZipURL, lowerPath, ver)) if err != nil { return "", err } @@ -55,7 +106,7 @@ func ProxyDownload(path string) (string, error) { return "", fmt.Errorf("status %d", resp.StatusCode) } - zipPath := filepath.Join(reposDir, filepath.Base(path)+"@"+mv.Version+".zip") + zipPath := filepath.Join(reposDir, filepath.Base(path)+"@"+ver+".zip") out, err := os.Create(zipPath) if err != nil { return "", err @@ -85,10 +136,10 @@ func ProxyDownload(path string) (string, error) { return "", err } - err = os.Rename(filepath.Join(reposDir, lowerPath+"@"+mv.Version), filepath.Join(reposDir, lowerPath)) + err = os.Rename(filepath.Join(reposDir, lowerPath+"@"+ver), filepath.Join(reposDir, lowerPath)) if err != nil { return "", err } - return mv.Version, nil + return ver, nil } diff --git a/handlers/check.go b/handlers/check.go index dc1ba78..a4fbc7e 100644 --- a/handlers/check.go +++ b/handlers/check.go @@ -28,6 +28,15 @@ func CheckHandler(w http.ResponseWriter, r *http.Request, db *badger.DB) { return } + moduleName, err := download.ModuleName(repo) + if err != nil { + log.Println("ERROR: could not get module name:", err) + } + + if moduleName != "" { + repo = moduleName + } + log.Printf("Checking repo %q...", repo) forceRefresh := r.Method != "GET" // if this is a GET request, try to fetch from cached version in badger first