Repository: moby/moby
File: daemon/server/router/container/container_routes.go (Go)

Code before:
	"github.com/docker/docker/api/types/backend"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/mount"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/api/types/versions"
	"github.com/docker/docker/daemon/libnetwork/netlabel"
	networkSettings "github.com/docker/docker/daemon/network"
	"github.com/docker/docker/daemon/server/httpstatus"
	"github.com/docker/docker/daemon/server/httputils"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/pkg/ioutils"
	"github.com/docker/docker/runconfig"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"go.opentelemetry.io/otel"
	"golang.org/x/net/websocket"
)

func (c *containerRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := httputils.ParseForm(r); err != nil {
		return err
	}

	var config *container.Config
	if err := httputils.ReadJSON(r, config); err != nil && !errors.Is(err, io.EOF) { // Do not fail if body is empty.
		return err
	}

	ref, err := httputils.RepoTagReference(r.Form.Get("repo"), r.Form.Get("tag"))
	if err != nil {
		return errdefs.InvalidParameter(err)
	}

	imgID, err := c.backend.CreateImageFromContainer(ctx, r.Form.Get("container"), &backend.CreateImageConfig{
		Pause:   httputils.BoolValueOrDefault(r, "pause", true), // TODO(dnephin): remove pause arg, and always pause in backend
		Tag:     ref,
		Author:  r.Form.Get("author"),
		Comment: r.Form.Get("comment"),
		Config:  config,
		Changes: r.Form["changes"],
	})
	if err != nil {
		return err
	}

	return httputils.WriteJSON(w, http.StatusCreated, &container.CommitResponse{ID: imgID})
}

func (c *containerRouter) getContainersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := httputils.ParseForm(r); err != nil {

Review comment (suggestion):
Checking for `io.EOF` looks redundant as well; `ReadJSON` returns `nil` for an empty Body;
https://github.com/moby/moby/blob/79f802d46a6087aaec68755de04b5cb7348858a9/daemon/server/httputils/httputils.go#L62-L71


It will return an error when getting an `io.EOF` on unmarshaling, but that would be invalid JSON;
https://github.com/moby/moby/blob/79f802d46a6087aaec68755de04b5cb7348858a9/daemon/server/httputils/httputils.go#L74-L79

Code after:
	networkSettings "github.com/docker/docker/daemon/network"
	"github.com/docker/docker/daemon/server/httpstatus"
	"github.com/docker/docker/daemon/server/httputils"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/pkg/ioutils"
	"github.com/docker/docker/runconfig"
	"github.com/moby/moby/api/types"
	"github.com/moby/moby/api/types/backend"
	"github.com/moby/moby/api/types/container"
	"github.com/moby/moby/api/types/filters"
	"github.com/moby/moby/api/types/mount"
	"github.com/moby/moby/api/types/network"
	"github.com/moby/moby/api/types/versions"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"go.opentelemetry.io/otel"
	"golang.org/x/net/websocket"
)

// commitRequest may contain an optional [container.Config].
type commitRequest struct {
	*container.Config
}

// decodeCommitRequest decodes the request body and returns a [container.Config]
// if present, or nil otherwise. It returns an error when failing to decode
// due to invalid JSON, or if the request contains multiple JSON documents.
//
// The client posts a bare [*container.Config] (see [Client.ContainerCommit]
// and [container.CommitOptions]), but it may be empty / nil, in which case
// it must be ignored, and no overrides to be applied.
//
// [Client.ContainerCommit]: https://github.com/moby/moby/blob/c4afa7715715a1020e50b19ad60728c4479fb0a5/client/container_commit.go#L52
// [container.CommitOptions]: https://github.com/moby/moby/blob/c4afa7715715a1020e50b19ad60728c4479fb0a5/api/types/container/options.go#L30
func decodeCommitRequest(r *http.Request) (*container.Config, error) {
	var w commitRequest
	if err := httputils.ReadJSON(r, &w); err != nil {
		return nil, err
	}
	return w.Config, nil
}

func (c *containerRouter) postCommit(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := httputils.ParseForm(r); err != nil {
		return err
	}

	config, err := decodeCommitRequest(r)
	if err != nil {
		return err
	}