diff --git a/app.go b/app.go index 63635250..bc7df554 100644 --- a/app.go +++ b/app.go @@ -29,10 +29,10 @@ func NewApp(configuration configuration.Configuration) *App { // Register the handler dispatchers. app.register(routeNameImageManifest, imageManifestDispatcher) - app.register(routeNameLayer, layerDispatcher) + app.register(routeNameBlob, layerDispatcher) app.register(routeNameTags, tagsDispatcher) - app.register(routeNameLayerUpload, layerUploadDispatcher) - app.register(routeNameLayerUploadResume, layerUploadDispatcher) + app.register(routeNameBlobUpload, layerUploadDispatcher) + app.register(routeNameBlobUploadResume, layerUploadDispatcher) return app } diff --git a/app_test.go b/app_test.go index e0fa727f..bb78044a 100644 --- a/app_test.go +++ b/app_test.go @@ -84,24 +84,22 @@ func TestAppDispatcher(t *testing.T) { }, }, { - endpoint: routeNameLayer, + endpoint: routeNameBlob, vars: []string{ "name", "foo/bar", - "tarsum", "tarsum.v1+bogus:abcdef0123456789", + "digest", "tarsum.v1+bogus:abcdef0123456789", }, }, { - endpoint: routeNameLayerUpload, + endpoint: routeNameBlobUpload, vars: []string{ "name", "foo/bar", - "tarsum", "tarsum.v1+bogus:abcdef0123456789", }, }, { - endpoint: routeNameLayerUploadResume, + endpoint: routeNameBlobUploadResume, vars: []string{ "name", "foo/bar", - "tarsum", "tarsum.v1+bogus:abcdef0123456789", "uuid", "theuuid", }, }, diff --git a/layer.go b/layer.go index 96920a8e..82a1e6d9 100644 --- a/layer.go +++ b/layer.go @@ -16,7 +16,8 @@ func layerDispatcher(ctx *Context, r *http.Request) http.Handler { layerHandler.log = layerHandler.log.WithField("tarsum", layerHandler.TarSum) return handlers.MethodHandler{ - "GET": http.HandlerFunc(layerHandler.GetLayer), + "GET": http.HandlerFunc(layerHandler.GetLayer), + "HEAD": http.HandlerFunc(layerHandler.GetLayer), } } diff --git a/layerupload.go b/layerupload.go index 3eb2ff9a..8916b552 100644 --- a/layerupload.go +++ b/layerupload.go @@ -24,6 +24,7 @@ func layerUploadDispatcher(ctx *Context, r *http.Request) http.Handler { return handlers.MethodHandler{ "POST": http.HandlerFunc(layerUploadHandler.StartLayerUpload), "GET": http.HandlerFunc(layerUploadHandler.GetUploadStatus), + "HEAD": http.HandlerFunc(layerUploadHandler.GetUploadStatus), "PUT": http.HandlerFunc(layerUploadHandler.PutLayerChunk), "DELETE": http.HandlerFunc(layerUploadHandler.CancelLayerUpload), } diff --git a/routes.go b/routes.go index 8da7c3e2..4aa0097f 100644 --- a/routes.go +++ b/routes.go @@ -6,19 +6,19 @@ import ( ) const ( - routeNameImageManifest = "image-manifest" - routeNameTags = "tags" - routeNameLayer = "layer" - routeNameLayerUpload = "layer-upload" - routeNameLayerUploadResume = "layer-upload-resume" + routeNameImageManifest = "image-manifest" + routeNameTags = "tags" + routeNameBlob = "blob" + routeNameBlobUpload = "blob-upload" + routeNameBlobUploadResume = "blob-upload-resume" ) var allEndpoints = []string{ routeNameImageManifest, routeNameTags, - routeNameLayer, - routeNameLayerUpload, - routeNameLayerUploadResume, + routeNameBlob, + routeNameBlobUpload, + routeNameBlobUploadResume, } // v2APIRouter builds a gorilla router with named routes for the various API @@ -27,11 +27,11 @@ func v2APIRouter() *mux.Router { router := mux.NewRouter(). StrictSlash(true) - // GET /v2//image/ Image Manifest Fetch the image manifest identified by name and tag. - // PUT /v2//image/ Image Manifest Upload the image manifest identified by name and tag. - // DELETE /v2//image/ Image Manifest Delete the image identified by name and tag. + // GET /v2//manifest/ Image Manifest Fetch the image manifest identified by name and tag. + // PUT /v2//manifest/ Image Manifest Upload the image manifest identified by name and tag. + // DELETE /v2//manifest/ Image Manifest Delete the image identified by name and tag. router. - Path("/v2/{name:" + common.RepositoryNameRegexp.String() + "}/image/{tag:" + common.TagNameRegexp.String() + "}"). + Path("/v2/{name:" + common.RepositoryNameRegexp.String() + "}/manifest/{tag:" + common.TagNameRegexp.String() + "}"). Name(routeNameImageManifest) // GET /v2//tags/list Tags Fetch the tags under the repository identified by name. @@ -39,22 +39,22 @@ func v2APIRouter() *mux.Router { Path("/v2/{name:" + common.RepositoryNameRegexp.String() + "}/tags/list"). Name(routeNameTags) - // GET /v2//layer/ Layer Fetch the layer identified by tarsum. + // GET /v2//blob/ Layer Fetch the blob identified by digest. router. - Path("/v2/{name:" + common.RepositoryNameRegexp.String() + "}/layer/{tarsum:" + common.TarsumRegexp.String() + "}"). - Name(routeNameLayer) + Path("/v2/{name:" + common.RepositoryNameRegexp.String() + "}/blob/{digest:[a-zA-Z0-9-_+.]+:[a-zA-Z0-9-_+.=]+}"). + Name(routeNameBlob) - // POST /v2//layer//upload/ Layer Upload Initiate an upload of the layer identified by tarsum. Requires length and a checksum parameter. + // POST /v2//blob/upload/ Layer Upload Initiate an upload of the layer identified by tarsum. router. - Path("/v2/{name:" + common.RepositoryNameRegexp.String() + "}/layer/{tarsum:" + common.TarsumRegexp.String() + "}/upload/"). - Name(routeNameLayerUpload) + Path("/v2/{name:" + common.RepositoryNameRegexp.String() + "}/blob/upload/"). + Name(routeNameBlobUpload) - // GET /v2//layer//upload/ Layer Upload Get the status of the upload identified by tarsum and uuid. - // PUT /v2//layer//upload/ Layer Upload Upload all or a chunk of the upload identified by tarsum and uuid. - // DELETE /v2//layer//upload/ Layer Upload Cancel the upload identified by layer and uuid + // GET /v2//blob/upload/ Layer Upload Get the status of the upload identified by tarsum and uuid. + // PUT /v2//blob/upload/ Layer Upload Upload all or a chunk of the upload identified by tarsum and uuid. + // DELETE /v2//blob/upload/ Layer Upload Cancel the upload identified by layer and uuid router. - Path("/v2/{name:" + common.RepositoryNameRegexp.String() + "}/layer/{tarsum:" + common.TarsumRegexp.String() + "}/upload/{uuid}"). - Name(routeNameLayerUploadResume) + Path("/v2/{name:" + common.RepositoryNameRegexp.String() + "}/blob/upload/{uuid}"). + Name(routeNameBlobUploadResume) return router } diff --git a/routes_test.go b/routes_test.go index 7ca51ae5..9085d302 100644 --- a/routes_test.go +++ b/routes_test.go @@ -48,7 +48,7 @@ func TestRouter(t *testing.T) { for _, testcase := range []routeTestCase{ { RouteName: routeNameImageManifest, - RequestURI: "/v2/foo/bar/image/tag", + RequestURI: "/v2/foo/bar/manifest/tag", Vars: map[string]string{ "name": "foo/bar", "tag": "tag", @@ -62,68 +62,75 @@ func TestRouter(t *testing.T) { }, }, { - RouteName: routeNameLayer, - RequestURI: "/v2/foo/bar/layer/tarsum.dev+foo:abcdef0919234", + RouteName: routeNameBlob, + RequestURI: "/v2/foo/bar/blob/tarsum.dev+foo:abcdef0919234", Vars: map[string]string{ "name": "foo/bar", - "tarsum": "tarsum.dev+foo:abcdef0919234", + "digest": "tarsum.dev+foo:abcdef0919234", }, }, { - RouteName: routeNameLayerUpload, - RequestURI: "/v2/foo/bar/layer/tarsum.dev+foo:abcdef0919234/upload/", + RouteName: routeNameBlob, + RequestURI: "/v2/foo/bar/blob/sha256:abcdef0919234", Vars: map[string]string{ "name": "foo/bar", - "tarsum": "tarsum.dev+foo:abcdef0919234", + "digest": "sha256:abcdef0919234", }, }, { - RouteName: routeNameLayerUploadResume, - RequestURI: "/v2/foo/bar/layer/tarsum.dev+foo:abcdef0919234/upload/uuid", + RouteName: routeNameBlobUpload, + RequestURI: "/v2/foo/bar/blob/upload/", Vars: map[string]string{ - "name": "foo/bar", - "tarsum": "tarsum.dev+foo:abcdef0919234", - "uuid": "uuid", + "name": "foo/bar", }, }, { - RouteName: routeNameLayerUploadResume, - RequestURI: "/v2/foo/bar/layer/tarsum.dev+foo:abcdef0919234/upload/D95306FA-FAD3-4E36-8D41-CF1C93EF8286", + RouteName: routeNameBlobUploadResume, + RequestURI: "/v2/foo/bar/blob/upload/uuid", Vars: map[string]string{ - "name": "foo/bar", - "tarsum": "tarsum.dev+foo:abcdef0919234", - "uuid": "D95306FA-FAD3-4E36-8D41-CF1C93EF8286", + "name": "foo/bar", + "uuid": "uuid", + }, + }, + { + RouteName: routeNameBlobUploadResume, + RequestURI: "/v2/foo/bar/blob/upload/D95306FA-FAD3-4E36-8D41-CF1C93EF8286", + Vars: map[string]string{ + "name": "foo/bar", + "uuid": "D95306FA-FAD3-4E36-8D41-CF1C93EF8286", + }, + }, + { + RouteName: routeNameBlobUploadResume, + RequestURI: "/v2/foo/bar/blob/upload/RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA==", + Vars: map[string]string{ + "name": "foo/bar", + "uuid": "RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA==", }, }, - { // Check ambiguity: ensure we can distinguish between tags for // "foo/bar/image/image" and image for "foo/bar/image" with tag // "tags" RouteName: routeNameImageManifest, - RequestURI: "/v2/foo/bar/image/image/tags", + RequestURI: "/v2/foo/bar/manifest/manifest/tags", Vars: map[string]string{ - "name": "foo/bar/image", + "name": "foo/bar/manifest", "tag": "tags", }, }, { // This case presents an ambiguity between foo/bar with tag="tags" - // and list tags for "foo/bar/image" + // and list tags for "foo/bar/manifest" RouteName: routeNameTags, - RequestURI: "/v2/foo/bar/image/tags/list", + RequestURI: "/v2/foo/bar/manifest/tags/list", Vars: map[string]string{ - "name": "foo/bar/image", + "name": "foo/bar/manifest", }, }, { - RouteName: routeNameLayerUploadResume, - RequestURI: "/v2/foo/../../layer/tarsum.dev+foo:abcdef0919234/upload/D95306FA-FAD3-4E36-8D41-CF1C93EF8286", - Vars: map[string]string{ - "name": "foo/bar", - "tarsum": "tarsum.dev+foo:abcdef0919234", - "uuid": "D95306FA-FAD3-4E36-8D41-CF1C93EF8286", - }, + RouteName: routeNameBlobUploadResume, + RequestURI: "/v2/foo/../../layer/upload/D95306FA-FAD3-4E36-8D41-CF1C93EF8286", StatusCode: http.StatusNotFound, }, } {