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
 | |
| }
 |