from . import base
from ..decorators import run_in_thread
+class NotFoundError(tornado.web.HTTPError):
+ def __init__(self):
+ super().__init__(status_code=404)
+
+
+class BlobUnknownError(NotFoundError):
+ """
+ Raised when we could not find the blob
+ """
+ pass
+
+
+class ManifestUnknownError(NotFoundError):
+ """
+ Raised when we could not find the manifest
+ """
+ pass
+
+
+class NameUnknownError(NotFoundError):
+ """
+ Raised when we could not find the distro
+ """
+ pass
+
+
class BaseHandler(base.BaseHandler):
"""
A base handler for any registry stuff
self.write(chunk)
async def write_error(self, *args, **kwargs):
- pass # Don't send any body
+ # Fetch the exception information
+ exc_info = kwargs.get("exc_info")
+
+ # Send nothing if we don't know enough about this error
+ if not exc_info:
+ return
+
+ # Unpack exception info
+ type, exception, traceback = exc_info
+
+ # Match our own API errors
+ if isinstance(exception, BlobUnknownError):
+ self.finish({
+ "errors" : [
+ { "code" : "BLOB_UNKNOWN" },
+ ],
+ })
+
+ elif isinstance(exception, ManifestUnknownError):
+ self.finish({
+ "errors" : [
+ { "code" : "MANIFEST_UNKNOWN" },
+ ],
+ })
+
+ elif isinstance(exception, NameUnknownError):
+ self.finish({
+ "errors" : [
+ { "code" : "NAME_UNKNOWN" },
+ ],
+ })
+
+ # Don't send anything for other errors
+ else:
+ pass
class NotFoundHandler(BaseHandler):
# Fetch the distribution
distro = await self.backend.distros.get_by_slug(distro_slug)
if not distro:
- raise tornado.web.HTTPError(404)
+ raise NameUnknownError
# Fetch the release
if label == "latest":
# Fail if we could not find a release
if not release:
- raise tornado.web.HTTPError(404)
+ raise ManifestUnknownError
# Check if the client supports the index format
if not self.client_accepts("application/vnd.oci.image.index.v1+json"):
# Fail if there are no OCI images
if not release.oci_images:
- raise tornado.web.HTTPError(404, "Release has no OCI images")
+ raise ManifestUnknownError
manifests = []
# Fetch the distribution
distro = await self.backend.distros.get_by_slug(distro_slug)
if not distro:
- raise tornado.web.HTTPError(404)
+ raise NameUnknownError
# Fetch the blob
blob = await self.get_blob(distro, digest)
if not blob:
- raise tornado.web.HTTPError(404)
+ raise BlobUnknownError
# Set Content-Type
self.set_header("Content-Type", "application/vnd.oci.image.manifest.v1+json")
# Fetch the distribution
distro = await self.backend.distros.get_by_slug(distro_slug)
if not distro:
- raise tornado.web.HTTPError(404)
+ raise NameUnknownError
# Fetch the blob
blob = await self.get_blob(distro, digest)
if not blob:
- raise tornado.web.HTTPError(404)
+ raise BlobUnknownError
# Set Content-Type
self.set_header("Content-Type", "application/octet-stream")