moby/integration/container/container_test.go
Sebastiaan van Stijn b6d58d749c
runconfig: ContainerDecoder(): fix handling of invalid JSON
Implement similar logic as is used in httputils.ReadJSON(). Before
this patch, endpoints using the ContainerDecoder would incorrectly
return a 500 (internal server error) status.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-04-11 21:44:45 +02:00

81 lines
2.7 KiB
Go

package container // import "github.com/docker/docker/integration/container"
import (
"net/http"
"runtime"
"testing"
"github.com/docker/docker/testutil/request"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
// TestContainerInvalidJSON tests that POST endpoints that expect a body return
// the correct error when sending invalid JSON requests.
func TestContainerInvalidJSON(t *testing.T) {
defer setupTest(t)()
// POST endpoints that accept / expect a JSON body;
endpoints := []string{
"/commit",
"/containers/create",
"/containers/foobar/exec",
"/containers/foobar/update",
"/exec/foobar/start",
}
// windows doesnt support API < v1.24
if runtime.GOOS != "windows" {
endpoints = append(
endpoints,
"/v1.23/containers/foobar/copy", // deprecated since 1.8 (API v1.20), errors out since 1.12 (API v1.24)
"/v1.23/containers/foobar/start", // accepts a body on API < v1.24
)
}
for _, ep := range endpoints {
ep := ep
t.Run(ep[1:], func(t *testing.T) {
t.Parallel()
t.Run("invalid content type", func(t *testing.T) {
res, body, err := request.Post(ep, request.RawString("{}"), request.ContentType("text/plain"))
assert.NilError(t, err)
assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest))
buf, err := request.ReadBody(body)
assert.NilError(t, err)
assert.Check(t, is.Contains(string(buf), "unsupported Content-Type header (text/plain): must be 'application/json'"))
})
t.Run("invalid JSON", func(t *testing.T) {
res, body, err := request.Post(ep, request.RawString("{invalid json"), request.JSON)
assert.NilError(t, err)
assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest))
buf, err := request.ReadBody(body)
assert.NilError(t, err)
assert.Check(t, is.Contains(string(buf), "invalid JSON: invalid character 'i' looking for beginning of object key string"))
})
t.Run("extra content after JSON", func(t *testing.T) {
res, body, err := request.Post(ep, request.RawString(`{} trailing content`), request.JSON)
assert.NilError(t, err)
assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest))
buf, err := request.ReadBody(body)
assert.NilError(t, err)
assert.Check(t, is.Contains(string(buf), "unexpected content after JSON"))
})
t.Run("empty body", func(t *testing.T) {
// empty body should not produce an 500 internal server error, or
// any 5XX error (this is assuming the request does not produce
// an internal server error for another reason, but it shouldn't)
res, _, err := request.Post(ep, request.RawString(``), request.JSON)
assert.NilError(t, err)
assert.Check(t, res.StatusCode < http.StatusInternalServerError)
})
})
}
}