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//manifests/ // // 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: // Docker-Content-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//manifests/ // // 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 // // is the namespace of the repository, and the 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: // // The 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//manifests/ 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) }