registry/layer.go
Stephen J Day 7b56d10076 Lock down HTTP API error codes
This commit locks down the set of http error codes that will be part of the
inital V2 specification, proposed in docker/docker#9015. The naming order has
been slightly changed and there are few tweaks to ensure all conditions are
captured but this will be set the docker core will be impleemnted against.

To support this, the errors have been moved into an api/errors package. A new
type, ErrorDescriptor, has been defined to centralize the code, message and
definitions used with each type. The information therein can be used to
generate documentation and response code mappings (yet to come...).

In addition to the refactoring that came along with this change, several tests
have been added to ensure serialization round trips are reliable. This allows
better support for using these error types on the client and server side. This
is coupled with some tweaks in the client code to fix issues with error
reporting.

Other fixes in the client include moving client-specific errors out of the base
package and ensuring that we have correct parameters for finishing uploads.
2014-12-10 11:49:04 -08:00

62 lines
1.5 KiB
Go

package registry
import (
"net/http"
"github.com/docker/docker-registry/api/errors"
"github.com/docker/docker-registry/digest"
"github.com/docker/docker-registry/storage"
"github.com/gorilla/handlers"
)
// layerDispatcher uses the request context to build a layerHandler.
func layerDispatcher(ctx *Context, r *http.Request) http.Handler {
dgst, err := digest.ParseDigest(ctx.vars["digest"])
if err != nil {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx.Errors.Push(errors.ErrorCodeDigestInvalid, err)
})
}
layerHandler := &layerHandler{
Context: ctx,
Digest: dgst,
}
layerHandler.log = layerHandler.log.WithField("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) {
layers := lh.services.Layers()
layer, err := layers.Fetch(lh.Name, lh.Digest)
if err != nil {
switch err := err.(type) {
case storage.ErrUnknownLayer:
w.WriteHeader(http.StatusNotFound)
lh.Errors.Push(errors.ErrorCodeBlobUnknown, err.FSLayer)
default:
lh.Errors.Push(errors.ErrorCodeUnknown, err)
}
return
}
defer layer.Close()
http.ServeContent(w, r, layer.Digest().String(), layer.CreatedAt(), layer)
}