d2bfb5825c
This changeset integrates contextual logging into the registry web application. Idiomatic context use is attempted within the current webapp layout. The functionality is centered around making lifecycle objects (application and request context) into contexts themselves. Relevant data has been moved into the context where appropriate. We still have some work to do to factor out the registry.Context object and the dispatching functionality to remove some awkward portions. The api tests were slightly refactored to use a test environment to eliminate common code. Signed-off-by: Stephen J Day <stephen.day@docker.com>
77 lines
1.8 KiB
Go
77 lines
1.8 KiB
Go
package registry
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/docker/distribution/api/v2"
|
|
ctxu "github.com/docker/distribution/context"
|
|
"github.com/docker/distribution/digest"
|
|
"github.com/docker/distribution/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 := 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 storage.ErrUnknownLayer:
|
|
w.WriteHeader(http.StatusNotFound)
|
|
lh.Errors.Push(v2.ErrorCodeBlobUnknown, err.FSLayer)
|
|
default:
|
|
lh.Errors.Push(v2.ErrorCodeUnknown, err)
|
|
}
|
|
return
|
|
}
|
|
defer layer.Close()
|
|
|
|
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)
|
|
}
|