mirror of https://github.com/goproxyio/goproxy
113 lines
2.9 KiB
Go
113 lines
2.9 KiB
Go
package proxy
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/goproxyio/goproxy/pkg/modfetch"
|
|
"github.com/goproxyio/goproxy/pkg/modfetch/codehost"
|
|
"github.com/goproxyio/goproxy/pkg/module"
|
|
)
|
|
|
|
var cacheDir string
|
|
var innerHandle http.Handler
|
|
|
|
func NewProxy(cache string) http.Handler {
|
|
modfetch.PkgMod = filepath.Join(cache, "pkg", "mod")
|
|
codehost.WorkRoot = filepath.Join(modfetch.PkgMod, "cache", "vcs")
|
|
|
|
cacheDir = filepath.Join(modfetch.PkgMod, "cache", "download")
|
|
innerHandle = http.FileServer(http.Dir(cacheDir))
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
log.Printf("goproxy: %s download %s\n", r.RemoteAddr, r.URL.Path)
|
|
if _, err := os.Stat(filepath.Join(cacheDir, r.URL.Path)); err != nil {
|
|
suffix := path.Ext(r.URL.Path)
|
|
if suffix == ".info" || suffix == ".mod" || suffix == ".zip" {
|
|
mod := strings.Split(r.URL.Path, "/@v/")
|
|
if len(mod) != 2 {
|
|
ReturnBadRequest(w, fmt.Errorf("bad module path:%s", r.URL.Path))
|
|
return
|
|
}
|
|
version := strings.TrimSuffix(mod[1], suffix)
|
|
version, err = module.DecodeVersion(version)
|
|
if err != nil {
|
|
ReturnServerError(w, err)
|
|
return
|
|
}
|
|
modPath := strings.TrimPrefix(mod[0], "/")
|
|
modPath, err := module.DecodePath(modPath)
|
|
if err != nil {
|
|
ReturnServerError(w, err)
|
|
return
|
|
}
|
|
// ignore the error, incorrect tag may be given
|
|
// forward to inner.ServeHTTP
|
|
if err := downloadMod(modPath, version); err != nil {
|
|
errLogger.Printf("download get err %s", err)
|
|
}
|
|
}
|
|
|
|
// fetch latest version
|
|
if strings.HasSuffix(r.URL.Path, "/@latest") {
|
|
modPath := strings.TrimSuffix(r.URL.Path, "/@latest")
|
|
modPath = strings.TrimPrefix(modPath, "/")
|
|
modPath, err := module.DecodePath(modPath)
|
|
if err != nil {
|
|
ReturnServerError(w, err)
|
|
return
|
|
}
|
|
repo, err := modfetch.Lookup(modPath)
|
|
if err != nil {
|
|
errLogger.Printf("lookup failed: %v", err)
|
|
ReturnServerError(w, err)
|
|
return
|
|
}
|
|
rev, err := repo.Stat("latest")
|
|
if err != nil {
|
|
errLogger.Printf("latest failed: %v", err)
|
|
return
|
|
}
|
|
if err := downloadMod(modPath, rev.Version); err != nil {
|
|
errLogger.Printf("download get err %s", err)
|
|
}
|
|
|
|
}
|
|
|
|
if strings.HasSuffix(r.URL.Path, "/@v/list") {
|
|
// TODO
|
|
_, _ = w.Write([]byte(""))
|
|
return
|
|
}
|
|
}
|
|
innerHandle.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
func downloadMod(modPath, version string) error {
|
|
if _, err := modfetch.InfoFile(modPath, version); err != nil {
|
|
return err
|
|
}
|
|
if _, err := modfetch.GoModFile(modPath, version); err != nil {
|
|
return err
|
|
}
|
|
if _, err := modfetch.GoModSum(modPath, version); err != nil {
|
|
return err
|
|
}
|
|
mod := module.Version{Path: modPath, Version: version}
|
|
if _, err := modfetch.DownloadZip(mod); err != nil {
|
|
return err
|
|
}
|
|
if a, err := modfetch.Download(mod); err != nil {
|
|
return err
|
|
} else {
|
|
log.Printf("goproxy: download %s@%s to dir %s\n", modPath, version, a)
|
|
}
|
|
return nil
|
|
}
|