Skip to content

ggcr: pkg/registry chunk upload endpoint returns HTTP 204 instead of HTTP 202 #2198

@wc9384

Description

@wc9384

Describe the bug

The registry implemented at github.com/google/go-containerregistry/pkg/registry returns an HTTP 204 No Content response on successful chunk uploads instead of a 202 Accepted, as the Docker HTTP API requires.

To Reproduce

Initiate an upload session with a POST request followed by a PATCH request containing a chunk to the URL given in the Location header provided in the response to the POST request. The registry will respond with an HTTP 204.

Attached is a simple script that confirms the problem:

package main

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"time"

	"github.com/google/go-containerregistry/pkg/registry"
)

func main() {
	// create and start the registry server
	regAddr := "localhost:5000"
	repo := "mynamespace/myrepo"

	handler := registry.New()
	srv := &http.Server{
		Addr:    regAddr,
		Handler: handler,
	}

	go func() {
		if err := srv.ListenAndServe(); err != nil && !errors.Is(
			err, http.ErrServerClosed,
		) {
			fmt.Printf("ListenAndServe error: %v\n", err)
		}
	}()
	defer func() { _ = srv.Shutdown(context.Background()) }()

	// let the server start up
	time.Sleep(1 * time.Second)

	client := &http.Client{}

	// start the upload session
	resp, err := doRequest(
		client, "POST",
		fmt.Sprintf("http://%s/%s/blobs/uploads/", regAddr, repo), http.NoBody,
	)
	if err != nil {
		log.Fatal(err)
	}

	loc, err := resp.Location()
	if err != nil {
		log.Fatal(err)
	}

	// upload the first chunk
	buf := bytes.NewBufferString("abc")
	resp, err = doRequest(client, "PATCH", loc.String(), buf)
	if err != nil {
		log.Fatal(err)
	}

	// check the response status code
	if resp.StatusCode != http.StatusAccepted {
		fmt.Printf("Expected HTTP status 202, but got %d", resp.StatusCode)
	}
}

func doRequest(
	client *http.Client, method string, url string, body io.Reader,
) (*http.Response, error) {
	req, err := http.NewRequest(method, url, body)
	if err != nil {
		return nil, err
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}

	err = resp.Body.Close()
	if err != nil {
		return nil, err
	}
	return resp, nil
}

Expected behavior

Expect the response code for the PATCH request to be HTTP 202 Accepted, as described by the Docker API Registry spec and the Distribution HTTP API V2 spec.

Additional context

Add any other context about the problem here.

  • Version of the module
  • Registry used (e.g., GCR, ECR, Quay)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions