...

Source file src/github.com/docker/distribution/registry/handlers/blob.go

Documentation: github.com/docker/distribution/registry/handlers

     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/registry/api/errcode"
     9  	v2 "github.com/docker/distribution/registry/api/v2"
    10  	"github.com/gorilla/handlers"
    11  	"github.com/opencontainers/go-digest"
    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  }
   100  

View as plain text