115 lines
4.1 KiB
Go
115 lines
4.1 KiB
Go
package handler
|
|
|
|
import (
|
|
//"mstore/app/descr"
|
|
"mstore/app/operator"
|
|
"mstore/app/router"
|
|
)
|
|
|
|
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md
|
|
//
|
|
// Open Container Initiative Distribution Specification
|
|
//
|
|
// Existing Manifests
|
|
//
|
|
// The image manifest can be checked for existence with the following url:
|
|
//
|
|
// HEAD /v2/<name>/manifests/<reference>
|
|
//
|
|
// The name and reference parameter identify the image and are required. The reference may include a tag or digest.
|
|
//
|
|
// A 404 Not Found response will be returned if the image is unknown to the registry.
|
|
// If the image exists and the response is successful the response will be as follows:
|
|
//
|
|
// 200 OK
|
|
// Content-Length: <length of manifest>
|
|
// Docker-Content-Digest: <digest>
|
|
|
|
func (hand *Handler) ManifestExists(rctx *router.Context) {
|
|
name, _ := rctx.GetSubpath("name")
|
|
reference, _ := rctx.GetSubpath("reference")
|
|
params := &operator.ManifestExistsParams{
|
|
Name: name,
|
|
Reference: reference,
|
|
}
|
|
ctx := rctx.GetContext()
|
|
res, code, err := hand.oper.ManifestExists(ctx, params)
|
|
if err != nil {
|
|
hand.logg.Errorf("ManifestExist error: %v", err)
|
|
} else if res.Exists {
|
|
rctx.SetHeader("Content-Length", res.ContentLength)
|
|
rctx.SetHeader("Content-Type", res.ContentType)
|
|
rctx.SetHeader("Docker-Content-Digest", res.DockerContentDigest)
|
|
}
|
|
rctx.SetStatus(code)
|
|
}
|
|
|
|
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md
|
|
//
|
|
// Pushing Manifests
|
|
//
|
|
// To push a manifest, perform a PUT request to a path in the following format,
|
|
// and with the following headers and body: /v2/<name>/manifests/<reference>
|
|
//
|
|
// Clients SHOULD set the Content-Type header to the type of the manifest being pushed.
|
|
// The client SHOULD NOT include parameters on the Content-Type header (see RFC7231).
|
|
// The registry SHOULD ignore parameters on the Content-Type header.
|
|
//
|
|
// All manifests SHOULD include a mediaType field declaring the type of the manifest being pushed.
|
|
// If a manifest includes a mediaType field, clients MUST set the Content-Type header to
|
|
// the value specified by the mediaType field.
|
|
//
|
|
// Content-Type: application/vnd.oci.image.manifest.v1+json
|
|
//
|
|
// <name> is the namespace of the repository, and the <reference> MUST be either a) a digest or b) a tag.
|
|
//
|
|
// The uploaded manifest MUST reference any blobs that make up the object.
|
|
// However, the list of blobs MAY be empty.
|
|
//
|
|
// The registry MUST store the manifest in the exact byte representation provided by the client.
|
|
// Upon a successful upload, the registry MUST return response code 201 Created,
|
|
// and MUST have the following header:
|
|
//
|
|
// Location: <location>
|
|
//
|
|
// The <location> is a pullable manifest URL. The Docker-Content-Digest header returns
|
|
// the canonical digest of the uploaded blob, and MUST be equal to the client provided digest.
|
|
// Clients MAY ignore the value but if it is used, the client SHOULD verify
|
|
// the value against the uploaded blob data.
|
|
//
|
|
// An attempt to pull a nonexistent repository MUST return response code 404 Not Found.
|
|
//
|
|
// A registry SHOULD enforce some limit on the maximum manifest size that it can accept.
|
|
// A registry that enforces this limit SHOULD respond to a request to push a manifest over this
|
|
// limit with a response code 413 Payload Too Large.
|
|
// Client and registry implementations SHOULD expect to be able to support manifest
|
|
// pushes of at least 4 megabytes.
|
|
|
|
// PUT /v2/<name>/manifests/<reference> 201 404
|
|
func (hand *Handler) PutManifest(rctx *router.Context) {
|
|
|
|
hand.DumpHeaders("PutManifest headers", rctx)
|
|
|
|
contentType := rctx.GetHeader("Content-Type")
|
|
contentLength := rctx.GetHeader("Content-Length")
|
|
|
|
name, _ := rctx.GetSubpath("name")
|
|
reference, _ := rctx.GetSubpath("reference")
|
|
|
|
params := &operator.PutManifestParams{
|
|
ContentType: contentType,
|
|
ContentLength: contentLength,
|
|
Name: name,
|
|
Reference: reference,
|
|
Reader: rctx.Request.Body,
|
|
}
|
|
ctx := rctx.GetContext()
|
|
res, code, err := hand.oper.PutManifest(ctx, params)
|
|
if err != nil {
|
|
hand.logg.Errorf("PutManifest error: %v", err)
|
|
} else {
|
|
rctx.SetHeader("Location", res.Location)
|
|
}
|
|
rctx.SetStatus(code)
|
|
}
|