forked from distribution/distribution
-
Notifications
You must be signed in to change notification settings - Fork 0
/
layer.go
78 lines (64 loc) · 1.88 KB
/
layer.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
package handlers
import (
"net/http"
"github.com/docker/distribution"
ctxu "github.com/docker/distribution/context"
"github.com/docker/distribution/digest"
"github.com/docker/distribution/registry/api/v2"
"github.com/gorilla/handlers"
)
// layerDispatcher uses the request context to build a layerHandler.
func layerDispatcher(ctx *Context, r *http.Request) http.Handler {
dgst, err := getDigest(ctx)
if err != nil {
if err == errDigestNotAvailable {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
ctx.Errors.Push(v2.ErrorCodeDigestInvalid, err)
})
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx.Errors.Push(v2.ErrorCodeDigestInvalid, err)
})
}
layerHandler := &layerHandler{
Context: ctx,
Digest: dgst,
}
return handlers.MethodHandler{
"GET": http.HandlerFunc(layerHandler.GetLayer),
"HEAD": http.HandlerFunc(layerHandler.GetLayer),
}
}
// layerHandler serves http layer requests.
type layerHandler struct {
*Context
Digest digest.Digest
}
// GetLayer fetches the binary data from backend storage returns it in the
// response.
func (lh *layerHandler) GetLayer(w http.ResponseWriter, r *http.Request) {
ctxu.GetLogger(lh).Debug("GetImageLayer")
layers := lh.Repository.Layers()
layer, err := layers.Fetch(lh.Digest)
if err != nil {
switch err := err.(type) {
case distribution.ErrUnknownLayer:
w.WriteHeader(http.StatusNotFound)
lh.Errors.Push(v2.ErrorCodeBlobUnknown, err.FSLayer)
default:
lh.Errors.Push(v2.ErrorCodeUnknown, err)
}
return
}
defer layer.Close()
w.Header().Set("Docker-Content-Digest", lh.Digest.String())
if lh.layerHandler != nil {
handler, _ := lh.layerHandler.Resolve(layer)
if handler != nil {
handler.ServeHTTP(w, r)
return
}
}
http.ServeContent(w, r, layer.Digest().String(), layer.CreatedAt(), layer)
}