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)master
							parent
							
								
									e062e66ee1
								
							
						
					
					
						commit
						db5689aa86
					
				|  | @ -108,10 +108,10 @@ type Layer interface { | |||
| 	// CreatedAt returns the time this layer was created.
 | ||||
| 	CreatedAt() time.Time | ||||
| 
 | ||||
| 	// ServeHTTP allows a layer to serve itself, whether by providing
 | ||||
| 	// a redirect directly to the content, or by serving the content
 | ||||
| 	// itself
 | ||||
| 	ServeHTTP(w http.ResponseWriter, r *http.Request) | ||||
| 	// Handler returns an HTTP handler which serves the layer content, whether
 | ||||
| 	// by providing a redirect directly to the content, or by serving the
 | ||||
| 	// content itself.
 | ||||
| 	Handler(r *http.Request) (http.Handler, error) | ||||
| } | ||||
| 
 | ||||
| // LayerUpload provides a handle for working with in-progress uploads.
 | ||||
|  |  | |||
|  | @ -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 New Issue