...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package registry
25
26 import (
27 "fmt"
28 "log"
29 "math/rand"
30 "net/http"
31 "os"
32 )
33
34 type registry struct {
35 log *log.Logger
36 blobs blobs
37 manifests manifests
38 referrersEnabled bool
39 warnings map[float64]string
40 }
41
42
43
44 func (r *registry) v2(resp http.ResponseWriter, req *http.Request) *regError {
45 if r.warnings != nil {
46 rnd := rand.Float64()
47 for prob, msg := range r.warnings {
48 if prob > rnd {
49 resp.Header().Add("Warning", fmt.Sprintf(`299 - "%s"`, msg))
50 }
51 }
52 }
53
54 if isBlob(req) {
55 return r.blobs.handle(resp, req)
56 }
57 if isManifest(req) {
58 return r.manifests.handle(resp, req)
59 }
60 if isTags(req) {
61 return r.manifests.handleTags(resp, req)
62 }
63 if isCatalog(req) {
64 return r.manifests.handleCatalog(resp, req)
65 }
66 if r.referrersEnabled && isReferrers(req) {
67 return r.manifests.handleReferrers(resp, req)
68 }
69 resp.Header().Set("Docker-Distribution-API-Version", "registry/2.0")
70 if req.URL.Path != "/v2/" && req.URL.Path != "/v2" {
71 return ®Error{
72 Status: http.StatusNotFound,
73 Code: "METHOD_UNKNOWN",
74 Message: "We don't understand your method + url",
75 }
76 }
77 resp.WriteHeader(200)
78 return nil
79 }
80
81 func (r *registry) root(resp http.ResponseWriter, req *http.Request) {
82 if rerr := r.v2(resp, req); rerr != nil {
83 r.log.Printf("%s %s %d %s %s", req.Method, req.URL, rerr.Status, rerr.Code, rerr.Message)
84 rerr.Write(resp)
85 return
86 }
87 r.log.Printf("%s %s", req.Method, req.URL)
88 }
89
90
91
92 func New(opts ...Option) http.Handler {
93 r := ®istry{
94 log: log.New(os.Stderr, "", log.LstdFlags),
95 blobs: blobs{
96 blobHandler: &memHandler{m: map[string][]byte{}},
97 uploads: map[string][]byte{},
98 log: log.New(os.Stderr, "", log.LstdFlags),
99 },
100 manifests: manifests{
101 manifests: map[string]map[string]manifest{},
102 log: log.New(os.Stderr, "", log.LstdFlags),
103 },
104 }
105 for _, o := range opts {
106 o(r)
107 }
108 return http.HandlerFunc(r.root)
109 }
110
111
112
113 type Option func(r *registry)
114
115
116 func Logger(l *log.Logger) Option {
117 return func(r *registry) {
118 r.log = l
119 r.manifests.log = l
120 r.blobs.log = l
121 }
122 }
123
124
125 func WithReferrersSupport(enabled bool) Option {
126 return func(r *registry) {
127 r.referrersEnabled = enabled
128 }
129 }
130
131 func WithWarning(prob float64, msg string) Option {
132 return func(r *registry) {
133 if r.warnings == nil {
134 r.warnings = map[float64]string{}
135 }
136 r.warnings[prob] = msg
137 }
138 }
139
140 func WithBlobHandler(h BlobHandler) Option {
141 return func(r *registry) {
142 r.blobs.blobHandler = h
143 }
144 }
145
View as plain text