Refactor Layer interface to return a Handler
... Rather than ServeHTTP directly. Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
This commit is contained in:
parent
fdd6314776
commit
6d14019368
3 changed files with 35 additions and 9 deletions
|
@ -63,5 +63,12 @@ func (lh *layerHandler) GetLayer(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
layer.ServeHTTP(w, r)
|
||||
handler, err := layer.Handler(r)
|
||||
if err != nil {
|
||||
ctxu.GetLogger(lh).Debugf("unexpected error getting layer HTTP handler: %s", err)
|
||||
lh.Errors.Push(v2.ErrorCodeUnknown, err)
|
||||
return
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ type StorageDriver interface {
|
|||
|
||||
// URLFor returns a URL which may be used to retrieve the content stored at
|
||||
// the given path, possibly using the given options.
|
||||
// May return an UnsupportedMethodErr in certain StorageDriver
|
||||
// May return an ErrUnsupportedMethod in certain StorageDriver
|
||||
// implementations.
|
||||
URLFor(path string, options map[string]interface{}) (string, error)
|
||||
}
|
||||
|
@ -85,8 +85,8 @@ type StorageDriver interface {
|
|||
// hyphen.
|
||||
var PathRegexp = regexp.MustCompile(`^(/[a-z0-9._-]+)+$`)
|
||||
|
||||
// UnsupportedMethodErr may be returned in the case where a StorageDriver implementation does not support an optional method.
|
||||
var ErrUnsupportedMethod = errors.New("Unsupported method")
|
||||
// ErrUnsupportedMethod may be returned in the case where a StorageDriver implementation does not support an optional method.
|
||||
var ErrUnsupportedMethod = errors.New("unsupported method")
|
||||
|
||||
// PathNotFoundError is returned when operating on a nonexistent path.
|
||||
type PathNotFoundError struct {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/digest"
|
||||
"github.com/docker/distribution/registry/storage/driver"
|
||||
)
|
||||
|
||||
// layerReader implements Layer and provides facilities for reading and
|
||||
|
@ -35,11 +36,29 @@ func (lr *layerReader) Close() error {
|
|||
return lr.closeWithErr(distribution.ErrLayerClosed)
|
||||
}
|
||||
|
||||
func (lr *layerReader) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Docker-Content-Digest", lr.digest.String())
|
||||
func (lr *layerReader) Handler(r *http.Request) (h http.Handler, err error) {
|
||||
var handlerFunc http.HandlerFunc
|
||||
|
||||
if url, err := lr.fileReader.driver.URLFor(lr.path, map[string]interface{}{"method": r.Method}); err == nil {
|
||||
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
|
||||
redirectURL, err := lr.fileReader.driver.URLFor(lr.path, map[string]interface{}{"method": r.Method})
|
||||
|
||||
switch err {
|
||||
case nil:
|
||||
handlerFunc = func(w http.ResponseWriter, r *http.Request) {
|
||||
// Redirect to storage URL.
|
||||
http.Redirect(w, r, redirectURL, http.StatusTemporaryRedirect)
|
||||
}
|
||||
case driver.ErrUnsupportedMethod:
|
||||
handlerFunc = func(w http.ResponseWriter, r *http.Request) {
|
||||
// Fallback to serving the content directly.
|
||||
http.ServeContent(w, r, lr.digest.String(), lr.CreatedAt(), lr)
|
||||
}
|
||||
default:
|
||||
// Some unexpected error.
|
||||
return nil, err
|
||||
}
|
||||
http.ServeContent(w, r, lr.digest.String(), lr.CreatedAt(), lr)
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Docker-Content-Digest", lr.digest.String())
|
||||
handlerFunc.ServeHTTP(w, r)
|
||||
}), nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue