forked from TrueCloudLab/distribution
Merge pull request #67 from BrianBland/layerhandler-http-method
Forwards http method to the layerhandler for layer serving
This commit is contained in:
commit
10c9dfb5a6
2 changed files with 38 additions and 6 deletions
|
@ -19,6 +19,7 @@ import (
|
||||||
type cloudFrontLayerHandler struct {
|
type cloudFrontLayerHandler struct {
|
||||||
cloudfront *cloudfront.CloudFront
|
cloudfront *cloudfront.CloudFront
|
||||||
delegateLayerHandler *delegateLayerHandler
|
delegateLayerHandler *delegateLayerHandler
|
||||||
|
duration time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ LayerHandler = &cloudFrontLayerHandler{}
|
var _ LayerHandler = &cloudFrontLayerHandler{}
|
||||||
|
@ -74,13 +75,28 @@ func newCloudFrontLayerHandler(storageDriver storagedriver.StorageDriver, option
|
||||||
|
|
||||||
cf := cloudfront.New(baseURL, privateKey, keypairID)
|
cf := cloudfront.New(baseURL, privateKey, keypairID)
|
||||||
|
|
||||||
return &cloudFrontLayerHandler{cloudfront: cf, delegateLayerHandler: dlh}, nil
|
duration := 20 * time.Minute
|
||||||
|
d, ok := options["duration"]
|
||||||
|
if ok {
|
||||||
|
switch d := d.(type) {
|
||||||
|
case time.Duration:
|
||||||
|
duration = d
|
||||||
|
case string:
|
||||||
|
dur, err := time.ParseDuration(d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid duration: %s", err)
|
||||||
|
}
|
||||||
|
duration = dur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cloudFrontLayerHandler{cloudfront: cf, delegateLayerHandler: dlh, duration: duration}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve returns an http.Handler which can serve the contents of the given
|
// Resolve returns an http.Handler which can serve the contents of the given
|
||||||
// Layer, or an error if not supported by the storagedriver.
|
// Layer, or an error if not supported by the storagedriver.
|
||||||
func (lh *cloudFrontLayerHandler) Resolve(layer Layer) (http.Handler, error) {
|
func (lh *cloudFrontLayerHandler) Resolve(layer Layer) (http.Handler, error) {
|
||||||
layerURLStr, err := lh.delegateLayerHandler.urlFor(layer)
|
layerURLStr, err := lh.delegateLayerHandler.urlFor(layer, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -90,7 +106,7 @@ func (lh *cloudFrontLayerHandler) Resolve(layer Layer) (http.Handler, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfURL, err := lh.cloudfront.CannedSignedURL(layerURL.Path, "", time.Now().Add(20*time.Minute))
|
cfURL, err := lh.cloudfront.CannedSignedURL(layerURL.Path, "", time.Now().Add(lh.duration))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,19 +41,30 @@ func newDelegateLayerHandler(storageDriver storagedriver.StorageDriver, options
|
||||||
// Resolve returns an http.Handler which can serve the contents of the given
|
// Resolve returns an http.Handler which can serve the contents of the given
|
||||||
// Layer, or an error if not supported by the storagedriver.
|
// Layer, or an error if not supported by the storagedriver.
|
||||||
func (lh *delegateLayerHandler) Resolve(layer Layer) (http.Handler, error) {
|
func (lh *delegateLayerHandler) Resolve(layer Layer) (http.Handler, error) {
|
||||||
layerURL, err := lh.urlFor(layer)
|
// TODO(bbland): This is just a sanity check to ensure that the
|
||||||
|
// storagedriver supports url generation. It would be nice if we didn't have
|
||||||
|
// to do this twice for non-GET requests.
|
||||||
|
layerURL, err := lh.urlFor(layer, map[string]interface{}{"method": "GET"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != "GET" {
|
||||||
|
layerURL, err = lh.urlFor(layer, map[string]interface{}{"method": r.Method})
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
http.Redirect(w, r, layerURL, http.StatusTemporaryRedirect)
|
http.Redirect(w, r, layerURL, http.StatusTemporaryRedirect)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// urlFor returns a download URL for the given layer, or the empty string if
|
// urlFor returns a download URL for the given layer, or the empty string if
|
||||||
// unsupported.
|
// unsupported.
|
||||||
func (lh *delegateLayerHandler) urlFor(layer Layer) (string, error) {
|
func (lh *delegateLayerHandler) urlFor(layer Layer, options map[string]interface{}) (string, error) {
|
||||||
// Crack open the layer to get at the layerStore
|
// Crack open the layer to get at the layerStore
|
||||||
layerRd, ok := layer.(*layerReader)
|
layerRd, ok := layer.(*layerReader)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -64,7 +75,12 @@ func (lh *delegateLayerHandler) urlFor(layer Layer) (string, error) {
|
||||||
return "", fmt.Errorf("unsupported layer type: cannot resolve blob path: %v", layer)
|
return "", fmt.Errorf("unsupported layer type: cannot resolve blob path: %v", layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
layerURL, err := lh.storageDriver.URLFor(layerRd.path, map[string]interface{}{"expiry": time.Now().Add(lh.duration)})
|
if options == nil {
|
||||||
|
options = make(map[string]interface{})
|
||||||
|
}
|
||||||
|
options["expiry"] = time.Now().Add(lh.duration)
|
||||||
|
|
||||||
|
layerURL, err := lh.storageDriver.URLFor(layerRd.path, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue