github.com/lusis/distribution@v2.0.1+incompatible/registry/storage/driver/base/base.go (about) 1 // Package base provides a base implementation of the storage driver that can 2 // be used to implement common checks. The goal is to increase the amount of 3 // code sharing. 4 // 5 // The canonical approach to use this class is to embed in the exported driver 6 // struct such that calls are proxied through this implementation. First, 7 // declare the internal driver, as follows: 8 // 9 // type driver struct { ... internal ...} 10 // 11 // The resulting type should implement StorageDriver such that it can be the 12 // target of a Base struct. The exported type can then be declared as follows: 13 // 14 // type Driver struct { 15 // Base 16 // } 17 // 18 // Because Driver embeds Base, it effectively implements Base. If the driver 19 // needs to intercept a call, before going to base, Driver should implement 20 // that method. Effectively, Driver can intercept calls before coming in and 21 // driver implements the actual logic. 22 // 23 // To further shield the embed from other packages, it is recommended to 24 // employ a private embed struct: 25 // 26 // type baseEmbed struct { 27 // base.Base 28 // } 29 // 30 // Then, declare driver to embed baseEmbed, rather than Base directly: 31 // 32 // type Driver struct { 33 // baseEmbed 34 // } 35 // 36 // The type now implements StorageDriver, proxying through Base, without 37 // exporting an unnecessary field. 38 package base 39 40 import ( 41 "io" 42 43 "github.com/docker/distribution/context" 44 storagedriver "github.com/docker/distribution/registry/storage/driver" 45 ) 46 47 // Base provides a wrapper around a storagedriver implementation that provides 48 // common path and bounds checking. 49 type Base struct { 50 storagedriver.StorageDriver 51 } 52 53 // GetContent wraps GetContent of underlying storage driver. 54 func (base *Base) GetContent(path string) ([]byte, error) { 55 _, done := context.WithTrace(context.Background()) 56 defer done("%s.GetContent(%q)", base.Name(), path) 57 58 if !storagedriver.PathRegexp.MatchString(path) { 59 return nil, storagedriver.InvalidPathError{Path: path} 60 } 61 62 return base.StorageDriver.GetContent(path) 63 } 64 65 // PutContent wraps PutContent of underlying storage driver. 66 func (base *Base) PutContent(path string, content []byte) error { 67 _, done := context.WithTrace(context.Background()) 68 defer done("%s.PutContent(%q)", base.Name(), path) 69 70 if !storagedriver.PathRegexp.MatchString(path) { 71 return storagedriver.InvalidPathError{Path: path} 72 } 73 74 return base.StorageDriver.PutContent(path, content) 75 } 76 77 // ReadStream wraps ReadStream of underlying storage driver. 78 func (base *Base) ReadStream(path string, offset int64) (io.ReadCloser, error) { 79 _, done := context.WithTrace(context.Background()) 80 defer done("%s.ReadStream(%q, %d)", base.Name(), path, offset) 81 82 if offset < 0 { 83 return nil, storagedriver.InvalidOffsetError{Path: path, Offset: offset} 84 } 85 86 if !storagedriver.PathRegexp.MatchString(path) { 87 return nil, storagedriver.InvalidPathError{Path: path} 88 } 89 90 return base.StorageDriver.ReadStream(path, offset) 91 } 92 93 // WriteStream wraps WriteStream of underlying storage driver. 94 func (base *Base) WriteStream(path string, offset int64, reader io.Reader) (nn int64, err error) { 95 _, done := context.WithTrace(context.Background()) 96 defer done("%s.WriteStream(%q, %d)", base.Name(), path, offset) 97 98 if offset < 0 { 99 return 0, storagedriver.InvalidOffsetError{Path: path, Offset: offset} 100 } 101 102 if !storagedriver.PathRegexp.MatchString(path) { 103 return 0, storagedriver.InvalidPathError{Path: path} 104 } 105 106 return base.StorageDriver.WriteStream(path, offset, reader) 107 } 108 109 // Stat wraps Stat of underlying storage driver. 110 func (base *Base) Stat(path string) (storagedriver.FileInfo, error) { 111 _, done := context.WithTrace(context.Background()) 112 defer done("%s.Stat(%q)", base.Name(), path) 113 114 if !storagedriver.PathRegexp.MatchString(path) { 115 return nil, storagedriver.InvalidPathError{Path: path} 116 } 117 118 return base.StorageDriver.Stat(path) 119 } 120 121 // List wraps List of underlying storage driver. 122 func (base *Base) List(path string) ([]string, error) { 123 _, done := context.WithTrace(context.Background()) 124 defer done("%s.List(%q)", base.Name(), path) 125 126 if !storagedriver.PathRegexp.MatchString(path) && path != "/" { 127 return nil, storagedriver.InvalidPathError{Path: path} 128 } 129 130 return base.StorageDriver.List(path) 131 } 132 133 // Move wraps Move of underlying storage driver. 134 func (base *Base) Move(sourcePath string, destPath string) error { 135 _, done := context.WithTrace(context.Background()) 136 defer done("%s.Move(%q, %q", base.Name(), sourcePath, destPath) 137 138 if !storagedriver.PathRegexp.MatchString(sourcePath) { 139 return storagedriver.InvalidPathError{Path: sourcePath} 140 } else if !storagedriver.PathRegexp.MatchString(destPath) { 141 return storagedriver.InvalidPathError{Path: destPath} 142 } 143 144 return base.StorageDriver.Move(sourcePath, destPath) 145 } 146 147 // Delete wraps Delete of underlying storage driver. 148 func (base *Base) Delete(path string) error { 149 _, done := context.WithTrace(context.Background()) 150 defer done("%s.Delete(%q)", base.Name(), path) 151 152 if !storagedriver.PathRegexp.MatchString(path) { 153 return storagedriver.InvalidPathError{Path: path} 154 } 155 156 return base.StorageDriver.Delete(path) 157 } 158 159 // URLFor wraps URLFor of underlying storage driver. 160 func (base *Base) URLFor(path string, options map[string]interface{}) (string, error) { 161 _, done := context.WithTrace(context.Background()) 162 defer done("%s.URLFor(%q)", base.Name(), path) 163 164 if !storagedriver.PathRegexp.MatchString(path) { 165 return "", storagedriver.InvalidPathError{Path: path} 166 } 167 168 return base.StorageDriver.URLFor(path, options) 169 }