github.com/lusis/distribution@v2.0.1+incompatible/registry/storage/layerreader.go (about)

     1  package storage
     2  
     3  import (
     4  	"net/http"
     5  	"time"
     6  
     7  	"github.com/docker/distribution"
     8  	"github.com/docker/distribution/digest"
     9  	"github.com/docker/distribution/registry/storage/driver"
    10  )
    11  
    12  // layerReader implements Layer and provides facilities for reading and
    13  // seeking.
    14  type layerReader struct {
    15  	fileReader
    16  
    17  	digest digest.Digest
    18  }
    19  
    20  // newLayerReader returns a new layerReader with the digest, path and length,
    21  // eliding round trips to the storage backend.
    22  func newLayerReader(driver driver.StorageDriver, dgst digest.Digest, path string, length int64) (*layerReader, error) {
    23  	fr := &fileReader{
    24  		driver: driver,
    25  		path:   path,
    26  		size:   length,
    27  	}
    28  
    29  	return &layerReader{
    30  		fileReader: *fr,
    31  		digest:     dgst,
    32  	}, nil
    33  }
    34  
    35  var _ distribution.Layer = &layerReader{}
    36  
    37  func (lr *layerReader) Digest() digest.Digest {
    38  	return lr.digest
    39  }
    40  
    41  func (lr *layerReader) Length() int64 {
    42  	return lr.size
    43  }
    44  
    45  func (lr *layerReader) CreatedAt() time.Time {
    46  	return lr.modtime
    47  }
    48  
    49  // Close the layer. Should be called when the resource is no longer needed.
    50  func (lr *layerReader) Close() error {
    51  	return lr.closeWithErr(distribution.ErrLayerClosed)
    52  }
    53  
    54  func (lr *layerReader) Handler(r *http.Request) (h http.Handler, err error) {
    55  	var handlerFunc http.HandlerFunc
    56  
    57  	redirectURL, err := lr.fileReader.driver.URLFor(lr.path, map[string]interface{}{"method": r.Method})
    58  
    59  	switch err {
    60  	case nil:
    61  		handlerFunc = func(w http.ResponseWriter, r *http.Request) {
    62  			// Redirect to storage URL.
    63  			http.Redirect(w, r, redirectURL, http.StatusTemporaryRedirect)
    64  		}
    65  	case driver.ErrUnsupportedMethod:
    66  		handlerFunc = func(w http.ResponseWriter, r *http.Request) {
    67  			// Fallback to serving the content directly.
    68  			http.ServeContent(w, r, lr.digest.String(), lr.CreatedAt(), lr)
    69  		}
    70  	default:
    71  		// Some unexpected error.
    72  		return nil, err
    73  	}
    74  
    75  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    76  		w.Header().Set("Docker-Content-Digest", lr.digest.String())
    77  		handlerFunc.ServeHTTP(w, r)
    78  	}), nil
    79  }