-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
106 lines (82 loc) · 1.81 KB
/
main.go
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
94
95
96
97
98
99
100
101
102
103
104
105
106
package main
import (
"flag"
"log"
"net/http"
"net/http/httputil"
"os"
"path"
"path/filepath"
"regexp"
"strings"
)
var (
bind = flag.String("addr", ":80", "bind address")
cacheDir = flag.String("cache", "cache", "cache dir")
rp = &httputil.ReverseProxy{
Director: func(_ *http.Request) {},
}
blobRE = regexp.MustCompile("/blobs/([[:alnum:]]+:[0-9a-f]+)$")
)
func main() {
flag.Parse()
for _, sub := range []string{"blobs"} {
if err := os.MkdirAll(filepath.Join(*cacheDir, sub), 0755); err != nil {
log.Fatal("failed to create cache dir: ", err)
}
}
if *cacheSize != 0 {
go cacheCleaner()
}
log.Print("listening on ", *bind)
err := http.ListenAndServe(*bind, handler{})
if err != nil {
log.Fatal(err)
}
}
type handler struct{}
func (_ handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
log := log.New(os.Stderr, req.RemoteAddr+": ", log.Flags())
if req.Method == http.MethodGet && strings.HasPrefix(req.URL.Path, "/blobs/") {
blob := path.Base(req.URL.Path)
serveBlob(w, req, blob, true)
return
}
u := req.URL
path := u.Path
if path[0] == '/' {
path = path[1:]
}
idx := strings.IndexByte(path, '/')
if idx == -1 {
w.Write([]byte("registries mirror\n"))
return
}
scheme := path[:idx]
path = path[idx+1:]
idx = strings.IndexByte(path, '/')
if idx == -1 {
u.Path = u.Path + "/"
http.Redirect(w, req, u.Path, http.StatusPermanentRedirect)
return
} else if idx == 0 {
http.NotFound(w, req)
return
}
host := path[:idx]
path = path[idx:]
u.Scheme = scheme
u.Host = host
req.Host = host
u.Path = path
if req.Method == http.MethodGet {
if m := blobRE.FindStringSubmatch(path); m != nil {
blob := m[1]
log.Print("serving blob ", blob)
serveBlob(w, req, blob, false)
return
}
}
log.Print("proxying ", u)
rp.ServeHTTP(w, req)
}