mirror of https://github.com/goproxyio/goproxy
golint
parent
914cff2342
commit
7472c4efb3
14
main.go
14
main.go
|
@ -158,10 +158,13 @@ type responseLogger struct {
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteHeader writes header code into responser writer.
|
||||||
func (r *responseLogger) WriteHeader(code int) {
|
func (r *responseLogger) WriteHeader(code int) {
|
||||||
r.code = code
|
r.code = code
|
||||||
r.ResponseWriter.WriteHeader(code)
|
r.ResponseWriter.WriteHeader(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServeHTTP implements http handler.
|
||||||
func (l *logger) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (l *logger) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
rl := &responseLogger{code: 200, ResponseWriter: w}
|
rl := &responseLogger{code: 200, ResponseWriter: w}
|
||||||
|
@ -172,9 +175,12 @@ func (l *logger) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// An ops is a proxy.ServerOps implementation.
|
// An ops is a proxy.ServerOps implementation.
|
||||||
type ops struct{}
|
type ops struct{}
|
||||||
|
|
||||||
|
// NewContext crates a context.
|
||||||
func (*ops) NewContext(r *http.Request) (context.Context, error) {
|
func (*ops) NewContext(r *http.Request) (context.Context, error) {
|
||||||
return context.Background(), nil
|
return context.Background(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List lists proxy files.
|
||||||
func (*ops) List(ctx context.Context, mpath string) (proxy.File, error) {
|
func (*ops) List(ctx context.Context, mpath string) (proxy.File, error) {
|
||||||
escMod, err := module.EscapePath(mpath)
|
escMod, err := module.EscapePath(mpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -209,6 +215,8 @@ func (*ops) List(ctx context.Context, mpath string) (proxy.File, error) {
|
||||||
|
|
||||||
return os.Open(file)
|
return os.Open(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Latest fetch latest file.
|
||||||
func (*ops) Latest(ctx context.Context, path string) (proxy.File, error) {
|
func (*ops) Latest(ctx context.Context, path string) (proxy.File, error) {
|
||||||
d, err := download(module.Version{Path: path, Version: "latest"})
|
d, err := download(module.Version{Path: path, Version: "latest"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -216,6 +224,8 @@ func (*ops) Latest(ctx context.Context, path string) (proxy.File, error) {
|
||||||
}
|
}
|
||||||
return os.Open(d.Info)
|
return os.Open(d.Info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info fetch info file.
|
||||||
func (*ops) Info(ctx context.Context, m module.Version) (proxy.File, error) {
|
func (*ops) Info(ctx context.Context, m module.Version) (proxy.File, error) {
|
||||||
d, err := download(m)
|
d, err := download(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -223,6 +233,8 @@ func (*ops) Info(ctx context.Context, m module.Version) (proxy.File, error) {
|
||||||
}
|
}
|
||||||
return os.Open(d.Info)
|
return os.Open(d.Info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GoMod fetch go mod file.
|
||||||
func (*ops) GoMod(ctx context.Context, m module.Version) (proxy.File, error) {
|
func (*ops) GoMod(ctx context.Context, m module.Version) (proxy.File, error) {
|
||||||
d, err := download(m)
|
d, err := download(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -230,6 +242,8 @@ func (*ops) GoMod(ctx context.Context, m module.Version) (proxy.File, error) {
|
||||||
}
|
}
|
||||||
return os.Open(d.GoMod)
|
return os.Open(d.GoMod)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zip fetch zip file.
|
||||||
func (*ops) Zip(ctx context.Context, m module.Version) (proxy.File, error) {
|
func (*ops) Zip(ctx context.Context, m module.Version) (proxy.File, error) {
|
||||||
d, err := download(m)
|
d, err := download(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
166
proxy/router.go
166
proxy/router.go
|
@ -34,16 +34,98 @@ type RouterOptions struct {
|
||||||
// which implements Route Filter to
|
// which implements Route Filter to
|
||||||
// routing private module or public module .
|
// routing private module or public module .
|
||||||
type Router struct {
|
type Router struct {
|
||||||
|
opts *RouterOptions
|
||||||
srv *Server
|
srv *Server
|
||||||
proxy *httputil.ReverseProxy
|
proxy *httputil.ReverseProxy
|
||||||
pattern string
|
pattern string
|
||||||
downloadRoot string
|
downloadRoot string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (router *Router) customModResponse(r *http.Response) error {
|
||||||
|
var err error
|
||||||
|
if r.StatusCode == http.StatusOK {
|
||||||
|
var buf []byte
|
||||||
|
if strings.Contains(r.Header.Get("Content-Encoding"), "gzip") {
|
||||||
|
gr, err := gzip.NewReader(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer gr.Close()
|
||||||
|
buf, err = ioutil.ReadAll(gr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.Header.Del("Content-Encoding")
|
||||||
|
} else {
|
||||||
|
buf, err = ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.Body = ioutil.NopCloser(bytes.NewReader(buf))
|
||||||
|
if buf != nil {
|
||||||
|
file := filepath.Join(router.opts.DownloadRoot, r.Request.URL.Path)
|
||||||
|
os.MkdirAll(path.Dir(file), os.ModePerm)
|
||||||
|
err = renameio.WriteFile(file, buf, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// support 302 status code.
|
||||||
|
if r.StatusCode == http.StatusFound {
|
||||||
|
loc := r.Header.Get("Location")
|
||||||
|
if loc == "" {
|
||||||
|
return fmt.Errorf("%d response missing Location header", r.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: location is relative.
|
||||||
|
_, err := url.Parse(loc)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse Location header %q: %v", loc, err)
|
||||||
|
}
|
||||||
|
resp, err := http.Get(loc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var buf []byte
|
||||||
|
if strings.Contains(resp.Header.Get("Content-Encoding"), "gzip") {
|
||||||
|
gr, err := gzip.NewReader(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer gr.Close()
|
||||||
|
buf, err = ioutil.ReadAll(gr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp.Header.Del("Content-Encoding")
|
||||||
|
} else {
|
||||||
|
buf, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp.Body = ioutil.NopCloser(bytes.NewReader(buf))
|
||||||
|
if buf != nil {
|
||||||
|
file := filepath.Join(router.opts.DownloadRoot, r.Request.URL.Path)
|
||||||
|
os.MkdirAll(path.Dir(file), os.ModePerm)
|
||||||
|
err = renameio.WriteFile(file, buf, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewRouter returns a new Router using the given operations.
|
// NewRouter returns a new Router using the given operations.
|
||||||
func NewRouter(srv *Server, opts *RouterOptions) *Router {
|
func NewRouter(srv *Server, opts *RouterOptions) *Router {
|
||||||
rt := &Router{
|
rt := &Router{
|
||||||
srv: srv,
|
opts: opts,
|
||||||
|
srv: srv,
|
||||||
}
|
}
|
||||||
if opts != nil {
|
if opts != nil {
|
||||||
if opts.Proxy == "" {
|
if opts.Proxy == "" {
|
||||||
|
@ -61,91 +143,14 @@ func NewRouter(srv *Server, opts *RouterOptions) *Router {
|
||||||
director(r)
|
director(r)
|
||||||
r.Host = remote.Host
|
r.Host = remote.Host
|
||||||
}
|
}
|
||||||
|
|
||||||
rt.proxy = proxy
|
rt.proxy = proxy
|
||||||
|
|
||||||
rt.proxy.Transport = &http.Transport{
|
rt.proxy.Transport = &http.Transport{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
}
|
}
|
||||||
rt.proxy.ModifyResponse = func(r *http.Response) error {
|
rt.proxy.ModifyResponse = rt.customModResponse
|
||||||
if r.StatusCode == http.StatusOK {
|
|
||||||
var buf []byte
|
|
||||||
if strings.Contains(r.Header.Get("Content-Encoding"), "gzip") {
|
|
||||||
gr, err := gzip.NewReader(r.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer gr.Close()
|
|
||||||
buf, err = ioutil.ReadAll(gr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.Header.Del("Content-Encoding")
|
|
||||||
} else {
|
|
||||||
buf, err = ioutil.ReadAll(r.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.Body = ioutil.NopCloser(bytes.NewReader(buf))
|
|
||||||
if buf != nil {
|
|
||||||
file := filepath.Join(opts.DownloadRoot, r.Request.URL.Path)
|
|
||||||
os.MkdirAll(path.Dir(file), os.ModePerm)
|
|
||||||
err = renameio.WriteFile(file, buf, 0666)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// support 302 status code.
|
|
||||||
if r.StatusCode == http.StatusFound {
|
|
||||||
loc := r.Header.Get("Location")
|
|
||||||
if loc == "" {
|
|
||||||
return fmt.Errorf("%d response missing Location header", r.StatusCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: location is relative.
|
|
||||||
_, err := url.Parse(loc)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to parse Location header %q: %v", loc, err)
|
|
||||||
}
|
|
||||||
resp, err := http.Get(loc)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
var buf []byte
|
|
||||||
if strings.Contains(resp.Header.Get("Content-Encoding"), "gzip") {
|
|
||||||
gr, err := gzip.NewReader(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer gr.Close()
|
|
||||||
buf, err = ioutil.ReadAll(gr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resp.Header.Del("Content-Encoding")
|
|
||||||
} else {
|
|
||||||
buf, err = ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resp.Body = ioutil.NopCloser(bytes.NewReader(buf))
|
|
||||||
if buf != nil {
|
|
||||||
file := filepath.Join(opts.DownloadRoot, r.Request.URL.Path)
|
|
||||||
os.MkdirAll(path.Dir(file), os.ModePerm)
|
|
||||||
err = renameio.WriteFile(file, buf, 0666)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
rt.pattern = opts.Pattern
|
rt.pattern = opts.Pattern
|
||||||
rt.downloadRoot = opts.DownloadRoot
|
rt.downloadRoot = opts.DownloadRoot
|
||||||
}
|
}
|
||||||
|
@ -160,6 +165,7 @@ func (rt *Router) Direct(path string) bool {
|
||||||
return GlobsMatchPath(rt.pattern, path)
|
return GlobsMatchPath(rt.pattern, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServveHTTP implements http handler.
|
||||||
func (rt *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (rt *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// sumdb handler
|
// sumdb handler
|
||||||
if strings.HasPrefix(r.URL.Path, "/sumdb/") {
|
if strings.HasPrefix(r.URL.Path, "/sumdb/") {
|
||||||
|
|
|
@ -221,8 +221,13 @@ type memFile struct {
|
||||||
stat memStat
|
stat memStat
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *memFile) Close() error { return nil }
|
// Close closes file.
|
||||||
func (f *memFile) Stat() (os.FileInfo, error) { return &f.stat, nil }
|
func (f *memFile) Close() error { return nil }
|
||||||
|
|
||||||
|
// Stat stats file.
|
||||||
|
func (f *memFile) Stat() (os.FileInfo, error) { return &f.stat, nil }
|
||||||
|
|
||||||
|
// Readdir read dir.
|
||||||
func (f *memFile) Readdir(count int) ([]os.FileInfo, error) { return nil, os.ErrInvalid }
|
func (f *memFile) Readdir(count int) ([]os.FileInfo, error) { return nil, os.ErrInvalid }
|
||||||
|
|
||||||
type memStat struct {
|
type memStat struct {
|
||||||
|
@ -230,12 +235,23 @@ type memStat struct {
|
||||||
size int64
|
size int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *memStat) Name() string { return "memfile" }
|
// Name returns file name.
|
||||||
func (s *memStat) Size() int64 { return s.size }
|
func (s *memStat) Name() string { return "memfile" }
|
||||||
func (s *memStat) Mode() os.FileMode { return 0444 }
|
|
||||||
|
// Size returns file size.
|
||||||
|
func (s *memStat) Size() int64 { return s.size }
|
||||||
|
|
||||||
|
// Mode returns file mode.
|
||||||
|
func (s *memStat) Mode() os.FileMode { return 0444 }
|
||||||
|
|
||||||
|
// ModTime returns file modtime.
|
||||||
func (s *memStat) ModTime() time.Time { return s.t }
|
func (s *memStat) ModTime() time.Time { return s.t }
|
||||||
func (s *memStat) IsDir() bool { return false }
|
|
||||||
func (s *memStat) Sys() interface{} { return nil }
|
// IsDir returns if file is a dir.
|
||||||
|
func (s *memStat) IsDir() bool { return false }
|
||||||
|
|
||||||
|
// Sys return nil.
|
||||||
|
func (s *memStat) Sys() interface{} { return nil }
|
||||||
|
|
||||||
// NewInfo returns a formatted info file for the given version, time pair.
|
// NewInfo returns a formatted info file for the given version, time pair.
|
||||||
// The version should be a canonical semantic version.
|
// The version should be a canonical semantic version.
|
||||||
|
|
|
@ -50,30 +50,15 @@ func Handler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
p := "https://" + strings.TrimPrefix(r.URL.Path, "/sumdb/")
|
p := "https://" + strings.TrimPrefix(r.URL.Path, "/sumdb/")
|
||||||
_, err := url.Parse(p)
|
proxySumdb(p, w, r)
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(http.StatusGone)
|
|
||||||
fmt.Fprintf(w, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := http.Get(p)
|
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(http.StatusGone)
|
|
||||||
fmt.Fprintf(w, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
w.WriteHeader(resp.StatusCode)
|
|
||||||
if _, err := io.Copy(w, resp.Body); err != nil {
|
|
||||||
fmt.Fprintf(w, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func sumViaGoproxy(w http.ResponseWriter, r *http.Request) {
|
func sumViaGoproxy(w http.ResponseWriter, r *http.Request) {
|
||||||
p := "https://goproxy.io" + r.URL.Path
|
p := "https://goproxy.io" + r.URL.Path
|
||||||
|
proxySumdb(p, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func proxySumdb(p string, w http.ResponseWriter, r *http.Request) {
|
||||||
_, err := url.Parse(p)
|
_, err := url.Parse(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusGone)
|
w.WriteHeader(http.StatusGone)
|
||||||
|
@ -94,4 +79,5 @@ func sumViaGoproxy(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue