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 }