# Manifests
(r"/v2/([a-z0-9]+(?:(?:\.|_|__|-+)[a-z0-9]+)*(?:\/[a-z0-9]+(?:(?:\.|_|__|-+)[a-z0-9]+)*)*)/manifests/([a-zA-Z0-9_][a-zA-Z0-9._-]{0,127})",
- registry.ManifestHandler),
+ registry.ManifestLabelHandler),
# Blobs & Manifests referenced by digest
- (r"/v2/([a-z0-9]+(?:(?:\.|_|__|-+)[a-z0-9]+)*(?:\/[a-z0-9]+(?:(?:\.|_|__|-+)[a-z0-9]+)*)*)/(blobs|manifests)/(sha256:[a-f0-9]{64})",
- registry.BlobOrManifestHandler),
+ (r"/v2/([a-z0-9]+(?:(?:\.|_|__|-+)[a-z0-9]+)*(?:\/[a-z0-9]+(?:(?:\.|_|__|-+)[a-z0-9]+)*)*)/manifests/(sha256:[a-f0-9]{64})",
+ registry.ManifestHandler),
+ (r"/v2/([a-z0-9]+(?:(?:\.|_|__|-+)[a-z0-9]+)*(?:\/[a-z0-9]+(?:(?:\.|_|__|-+)[a-z0-9]+)*)*)/blobs/(sha256:[a-f0-9]{64})",
+ registry.ManifestHandler),
# Catch anything else
(r"/v2/.*", registry.NotFoundHandler),
pass
-class ManifestHandler(BaseHandler):
+class ManifestLabelHandler(BaseHandler):
async def head(self, *args, **kwargs):
return await self.get(*args, **kwargs, send_body=False)
- async def get(self, distro_slug, release_slug, send_body=True):
+ async def get(self, distro_slug, label, send_body=True):
# Fetch the distribution
distro = await self.backend.distros.get_by_slug(distro_slug)
if not distro:
raise tornado.web.HTTPError(404)
# Fetch the release
- if release_slug == "latest":
+ if label == "latest":
release = await distro.get_latest_release()
else:
- release = await distro.get_release(release_slug)
+ release = await distro.get_release(label)
# Fail if we could not find a release
if not release:
self.finish(index)
-class BlobOrManifestHandler(BaseHandler):
+class ManifestHandler(BaseHandler):
async def head(self, *args, **kwargs):
return await self.get(*args, **kwargs, send_body=False)
- async def get(self, distro_slug, type, reference, send_body=True):
+ async def get(self, distro_slug, digest, send_body=True):
# Fetch the distribution
distro = await self.backend.distros.get_by_slug(distro_slug)
if not distro:
raise tornado.web.HTTPError(404)
# Fetch the blob
- blob = await self.get_blob(distro, reference)
+ blob = await self.get_blob(distro, digest)
if not blob:
raise tornado.web.HTTPError(404)
+ # Set Content-Type
+ self.set_header("Content-Type", "application/vnd.oci.image.manifest.v1+json")
+
# Send the blob!
- return await self._send_blob(blob, type, send_body=send_body)
+ if send_body:
+ await self.stream_blob(blob)
- async def _send_blob(self, blob, type, send_body=True):
- """
- Sends the blob to the client
- """
- # Set Content-Type
- if type == "manifests":
- self.set_header("Content-Type", "application/vnd.oci.image.manifest.v1+json")
- else:
- self.set_header("Content-Type", "application/octet-stream")
- # It would be nice to set Content-Length here, but there is no way to
- # determine the length of the file without reading the whole thing first.
+class BlobHandler(BaseHandler):
+ async def head(self, *args, **kwargs):
+ return await self.get(*args, **kwargs, send_body=False)
+
+ async def get(self, distro_slug, digest, send_body=True):
+ # Fetch the distribution
+ distro = await self.backend.distros.get_by_slug(distro_slug)
+ if not distro:
+ raise tornado.web.HTTPError(404)
+
+ # Fetch the blob
+ blob = await self.get_blob(distro, digest)
+ if not blob:
+ raise tornado.web.HTTPError(404)
- # Done if we should not send the body
+ # Set Content-Type
+ self.set_header("Content-Type", "application/octet-stream")
+
+ # Send the blob!
if send_body:
await self.stream_blob(blob)