mirror of https://github.com/goproxyio/goproxy
				
				
				
			
		
			
				
	
	
		
			111 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			111 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)
 | 
						|
				}
 | 
						|
				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
 | 
						|
}
 |