server.go

v1.1.0
Doc Versions Source
1
package server
2
3
import (
4
	"fmt"
5
	"net/http"
6
	"strconv"
7
	"time"
8
9
	"example.com/curator/internal/config"
10
	"example.com/curator/internal/dochtml"
11
	"example.com/curator/internal/git"
12
	"example.com/curator/internal/metrics"
13
	"example.com/curator/internal/storage"
14
	"example.com/curator/internal/store"
15
)
16
17
type Server struct {
18
	Cfg         *config.Config
19
	Resolver    store.ModuleResolver
20
	Git         *git.Cache
21
	Store       storage.Storage
22
	AuthTokens  map[string]struct{}
23
	HTTPClient  *http.Client
24
	DocRenderer *dochtml.Renderer
25
}
26
27
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
28
	handler := "import"
29
	start := time.Now()
30
31
	rw := &responseWriter{ResponseWriter: w, code: http.StatusOK}
32
33
	defer func() {
34
		metrics.HTTPRequestsTotal.WithLabelValues(handler, r.Method, strconv.Itoa(rw.code)).Inc()
35
		metrics.HTTPRequestDuration.WithLabelValues(handler).Observe(time.Since(start).Seconds())
36
	}()
37
38
	// Handle GOPROXY @latest requests.
39
	if escapedModPath, ok := ParseLatestPath(r.URL.Path); ok {
40
		handler = "proxy"
41
		s.serveLatest(rw, r, escapedModPath)
42
		return
43
	}
44
45
	// Handle GOPROXY requests.
46
	if modName, file, ok := ParseProxyPath(r.URL.Path); ok {
47
		handler = "proxy"
48
		s.serveProxy(rw, r, modName, file)
49
		return
50
	}
51
52
	name := ModuleName(r.URL.Path)
53
	if name == "" {
54
		http.NotFound(rw, r)
55
		return
56
	}
57
58
	if !s.CanAccessModule(name, r) {
59
		http.NotFound(rw, r)
60
		return
61
	}
62
63
	mod, _ := s.Resolver.ResolveModule(name)
64
65
	importPrefix := s.Cfg.Host + "/" + name
66
67
	// If not a go-get request, serve documentation.
68
	if r.URL.Query().Get("go-get") != "1" {
69
		if s.DocRenderer != nil {
70
			handler = "docs"
71
			s.serveDocs(rw, r)
72
			return
73
		}
74
75
		if mod.Web != "" {
76
			http.Redirect(rw, r, mod.Web, http.StatusTemporaryRedirect)
77
			return
78
		}
79
80
		http.NotFound(rw, r)
81
		return
82
	}
83
84
	rw.Header().Set("Content-Type", "text/html; charset=utf-8")
85
	fmt.Fprintf(rw, `<!DOCTYPE html>
86
<html>
87
<head>
88
<meta name="go-import" content="%s %s %s">
89
<meta http-equiv="refresh" content="0; url=%s">
90
</head>
91
<body>
92
Redirecting to <a href="%s">%s</a>...
93
</body>
94
</html>
95
`, importPrefix, mod.VCS, mod.Repo, mod.Web, mod.Web, mod.Web)
96
}
97

Source Files