Merge pull request #261 from jlhawn/url_for_method
Refactor Layer interface to return a Handlermaster
						commit
						47cf298bd0
					
				| 
						 | 
					@ -108,10 +108,10 @@ type Layer interface {
 | 
				
			||||||
	// CreatedAt returns the time this layer was created.
 | 
						// CreatedAt returns the time this layer was created.
 | 
				
			||||||
	CreatedAt() time.Time
 | 
						CreatedAt() time.Time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ServeHTTP allows a layer to serve itself, whether by providing
 | 
						// Handler returns an HTTP handler which serves the layer content, whether
 | 
				
			||||||
	// a redirect directly to the content, or by serving the content
 | 
						// by providing a redirect directly to the content, or by serving the
 | 
				
			||||||
	// itself
 | 
						// content itself.
 | 
				
			||||||
	ServeHTTP(w http.ResponseWriter, r *http.Request)
 | 
						Handler(r *http.Request) (http.Handler, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LayerUpload provides a handle for working with in-progress uploads.
 | 
					// 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
 | 
							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
 | 
						// URLFor returns a URL which may be used to retrieve the content stored at
 | 
				
			||||||
	// the given path, possibly using the given options.
 | 
						// the given path, possibly using the given options.
 | 
				
			||||||
	// May return an UnsupportedMethodErr in certain StorageDriver
 | 
						// May return an ErrUnsupportedMethod in certain StorageDriver
 | 
				
			||||||
	// implementations.
 | 
						// implementations.
 | 
				
			||||||
	URLFor(path string, options map[string]interface{}) (string, error)
 | 
						URLFor(path string, options map[string]interface{}) (string, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -85,8 +85,8 @@ type StorageDriver interface {
 | 
				
			||||||
// hyphen.
 | 
					// hyphen.
 | 
				
			||||||
var PathRegexp = regexp.MustCompile(`^(/[a-z0-9._-]+)+$`)
 | 
					var PathRegexp = regexp.MustCompile(`^(/[a-z0-9._-]+)+$`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UnsupportedMethodErr may be returned in the case where a StorageDriver implementation does not support an optional method.
 | 
					// ErrUnsupportedMethod may be returned in the case where a StorageDriver implementation does not support an optional method.
 | 
				
			||||||
var ErrUnsupportedMethod = errors.New("Unsupported method")
 | 
					var ErrUnsupportedMethod = errors.New("unsupported method")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PathNotFoundError is returned when operating on a nonexistent path.
 | 
					// PathNotFoundError is returned when operating on a nonexistent path.
 | 
				
			||||||
type PathNotFoundError struct {
 | 
					type PathNotFoundError struct {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/docker/distribution"
 | 
						"github.com/docker/distribution"
 | 
				
			||||||
	"github.com/docker/distribution/digest"
 | 
						"github.com/docker/distribution/digest"
 | 
				
			||||||
 | 
						"github.com/docker/distribution/registry/storage/driver"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// layerReader implements Layer and provides facilities for reading and
 | 
					// layerReader implements Layer and provides facilities for reading and
 | 
				
			||||||
| 
						 | 
					@ -35,11 +36,29 @@ func (lr *layerReader) Close() error {
 | 
				
			||||||
	return lr.closeWithErr(distribution.ErrLayerClosed)
 | 
						return lr.closeWithErr(distribution.ErrLayerClosed)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (lr *layerReader) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
					func (lr *layerReader) Handler(r *http.Request) (h http.Handler, err error) {
 | 
				
			||||||
	w.Header().Set("Docker-Content-Digest", lr.digest.String())
 | 
						var handlerFunc http.HandlerFunc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if url, err := lr.fileReader.driver.URLFor(lr.path, map[string]interface{}{"method": r.Method}); err == nil {
 | 
						redirectURL, err := lr.fileReader.driver.URLFor(lr.path, map[string]interface{}{"method": r.Method})
 | 
				
			||||||
		http.Redirect(w, r, url, http.StatusTemporaryRedirect)
 | 
					
 | 
				
			||||||
 | 
						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)
 | 
								http.ServeContent(w, r, lr.digest.String(), lr.CreatedAt(), lr)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							// Some unexpected error.
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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