github.com/npaton/distribution@v2.3.1-rc.0+incompatible/registry/handlers/blob.go (about) 1 package handlers 2 3 import ( 4 "net/http" 5 6 "github.com/docker/distribution" 7 "github.com/docker/distribution/context" 8 "github.com/docker/distribution/digest" 9 "github.com/docker/distribution/registry/api/errcode" 10 "github.com/docker/distribution/registry/api/v2" 11 "github.com/gorilla/handlers" 12 ) 13 14 // blobDispatcher uses the request context to build a blobHandler. 15 func blobDispatcher(ctx *Context, r *http.Request) http.Handler { 16 dgst, err := getDigest(ctx) 17 if err != nil { 18 19 if err == errDigestNotAvailable { 20 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 21 ctx.Errors = append(ctx.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err)) 22 }) 23 } 24 25 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 26 ctx.Errors = append(ctx.Errors, v2.ErrorCodeDigestInvalid.WithDetail(err)) 27 }) 28 } 29 30 blobHandler := &blobHandler{ 31 Context: ctx, 32 Digest: dgst, 33 } 34 35 mhandler := handlers.MethodHandler{ 36 "GET": http.HandlerFunc(blobHandler.GetBlob), 37 "HEAD": http.HandlerFunc(blobHandler.GetBlob), 38 } 39 40 if !ctx.readOnly { 41 mhandler["DELETE"] = http.HandlerFunc(blobHandler.DeleteBlob) 42 } 43 44 return mhandler 45 } 46 47 // blobHandler serves http blob requests. 48 type blobHandler struct { 49 *Context 50 51 Digest digest.Digest 52 } 53 54 // GetBlob fetches the binary data from backend storage returns it in the 55 // response. 56 func (bh *blobHandler) GetBlob(w http.ResponseWriter, r *http.Request) { 57 context.GetLogger(bh).Debug("GetBlob") 58 blobs := bh.Repository.Blobs(bh) 59 desc, err := blobs.Stat(bh, bh.Digest) 60 if err != nil { 61 if err == distribution.ErrBlobUnknown { 62 bh.Errors = append(bh.Errors, v2.ErrorCodeBlobUnknown.WithDetail(bh.Digest)) 63 } else { 64 bh.Errors = append(bh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) 65 } 66 return 67 } 68 69 if err := blobs.ServeBlob(bh, w, r, desc.Digest); err != nil { 70 context.GetLogger(bh).Debugf("unexpected error getting blob HTTP handler: %v", err) 71 bh.Errors = append(bh.Errors, errcode.ErrorCodeUnknown.WithDetail(err)) 72 return 73 } 74 } 75 76 // DeleteBlob deletes a layer blob 77 func (bh *blobHandler) DeleteBlob(w http.ResponseWriter, r *http.Request) { 78 context.GetLogger(bh).Debug("DeleteBlob") 79 80 blobs := bh.Repository.Blobs(bh) 81 err := blobs.Delete(bh, bh.Digest) 82 if err != nil { 83 switch err { 84 case distribution.ErrUnsupported: 85 bh.Errors = append(bh.Errors, errcode.ErrorCodeUnsupported) 86 return 87 case distribution.ErrBlobUnknown: 88 bh.Errors = append(bh.Errors, v2.ErrorCodeBlobUnknown) 89 return 90 default: 91 bh.Errors = append(bh.Errors, err) 92 context.GetLogger(bh).Errorf("Unknown error deleting blob: %s", err.Error()) 93 return 94 } 95 } 96 97 w.Header().Set("Content-Length", "0") 98 w.WriteHeader(http.StatusAccepted) 99 }