1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
package repo
import (
"bytes"
_ "embed"
"fmt"
"html/template"
"net/http"
"strings"
)
//go:embed meta.html
var tmplStr string
type Repo struct {
VCS string `toml:"vcs"`
Repository string `toml:"repo"`
Home string `toml:"source,omitempty"`
Directory string `toml:"directory"`
File string `toml:"file"`
}
type RepoHandler struct {
Pages map[string][]byte
}
func New(repo map[string]Repo) (*RepoHandler, error) {
m, err := NewMeta()
if err != nil {
return nil, err
}
h := &RepoHandler{Pages: map[string][]byte{}}
for k, v := range repo {
if v.Home == "" {
v.Home = "_"
}
b, err := m.Exec(k, v)
if err != nil {
return nil, err
}
h.Pages[k] = b
}
return h, nil
}
func (h *RepoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
key := fmt.Sprintf("%s%s", r.Host, r.URL.Path)
key = strings.TrimSuffix(key, "/")
page, ok := h.Pages[key]
if !ok {
http.NotFound(w, r)
return
}
if r.FormValue("go-get") == "1" {
w.Header().Set("Cache-Control", "public, max-age=86400, immutable")
w.Header().Set("Vary", "Host")
w.Header().Set("Content-Type", "text/html")
w.Write(page)
} else {
url := fmt.Sprintf("https://pkg.go.dev/%s", key)
http.Redirect(w, r, url, http.StatusFound)
}
}
type Meta struct {
tmpl *template.Template
}
func NewMeta() (*Meta, error) {
tmpl, err := template.New("meta").Parse(tmplStr)
if err != nil {
return nil, err
}
return &Meta{tmpl: tmpl}, nil
}
func (m *Meta) Exec(pkg string, repo Repo) ([]byte, error) {
var buf bytes.Buffer
data := struct {
Package string
Repo
}{
Package: pkg,
Repo: repo,
}
if err := m.tmpl.Execute(&buf, data); err != nil {
return nil, fmt.Errorf("exec template for %v: %w", pkg, err)
}
return buf.Bytes(), nil
}
|