Skip to content

api/server/httputils: add ReadJSON() utility and fix handling of invalid JSON#43463

Merged
thaJeztah merged 4 commits into
moby:masterfrom
thaJeztah:httputils_readjson
Apr 11, 2022
Merged

api/server/httputils: add ReadJSON() utility and fix handling of invalid JSON#43463
thaJeztah merged 4 commits into
moby:masterfrom
thaJeztah:httputils_readjson

Conversation

@thaJeztah
Copy link
Copy Markdown
Member

Implement a httputils.ReadJSON() utility to help reduce some code-duplication, and to make sure we handle JSON requests consistently (e.g. always check for the content-type).

Differences compared to current handling:

  • prevent possible panic if request.Body is nil ("should never happen")
  • always require Content-Type to be "application/json"
  • be stricter about additional content after JSON (previously ignored)
  • close body after reading (some code did this)

We should consider to add a "max body size" on this function, similar to

maxBodySize := 4096 // 4KB
if r.ContentLength > int64(maxBodySize) {
return handler(ctx, w, r, vars)
}
body := r.Body
bufReader := bufio.NewReaderSize(body, maxBodySize)
r.Body = ioutils.NewReadCloserWrapper(bufReader, func() error { return body.Close() })
b, err := bufReader.Peek(maxBodySize)
if err != io.EOF {
// either there was an error reading, or the buffer is full (in which case the request is too large)
return handler(ctx, w, r, vars)
}

In addition to the changes above, two commits are included in this PR that:

  • api/server/httputils: matchesContentType(): return error instead of logging
  • api/server/httputils: move WriteJSON() together with ReadJSON()

- Description for the changelog

API: Improve validation of invalid JSON requests

- A picture of a cute animal (not mandatory but encouraged)

Comment thread api/server/httputils/httputils.go
@thaJeztah thaJeztah force-pushed the httputils_readjson branch from a7b55f2 to 2d95e3b Compare April 8, 2022 21:31
@thaJeztah thaJeztah changed the title api/server/httputils: add ReadJSON() utility api/server/httputils: add ReadJSON() utility and fix handling of invalid JSON Apr 8, 2022
@thaJeztah thaJeztah force-pushed the httputils_readjson branch 4 times, most recently from ee3c291 to 34c20ce Compare April 10, 2022 21:23
@thaJeztah thaJeztah marked this pull request as ready for review April 10, 2022 22:32
Copy link
Copy Markdown
Member

@samuelkarp samuelkarp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good improvement to consistency and readability, LGTM!

return errdefs.InvalidParameter(errors.Wrap(err, "invalid JSON"))
}

if dec.More() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this method (officially/intentionally) still work correctly after the body is closed?
(The implementation in it appears to do a peek() but I'm not sure if that's on an internal buffer?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the r.Body.Close() to a defer r.Body.Close(), just in case 👍

Comment thread runconfig/config.go
return w.Config, hc, w.NetworkingConfig, nil
}

func loadJSON(src io.Reader, out interface{}) error {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could have a very small comment that explains why this is separate with a link back to the "original" implementation? 😇

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment:

// loadJSON is similar to api/server/httputils.ReadJSON()

@tianon
Copy link
Copy Markdown
Member

tianon commented Apr 11, 2022

(Two minor comments - neither are blockers IMO)

Implement a ReadJSON() utility to help reduce some code-duplication,
and to make sure we handle JSON requests consistently (e.g. always
check for the content-type).

Differences compared to current handling:

- prevent possible panic if request.Body is nil ("should never happen")
- always require Content-Type to be "application/json"
- be stricter about additional content after JSON (previously ignored)
- but, allow the body to be empty (an empty body is not invalid);
  update TestContainerInvalidJSON accordingly, which was testing the
  wrong expectation.
- close body after reading (some code did this)

We should consider to add a "max body size" on this function, similar to
https://github.com/moby/moby/blob/7b9275c0da707b030e62c96b679a976f31f929d3/api/server/middleware/debug.go#L27-L40

Signed-off-by: Sebastiaan van Stijn <[email protected]>
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 <[email protected]>
@thaJeztah thaJeztah force-pushed the httputils_readjson branch from 34c20ce to b6d58d7 Compare April 11, 2022 19:45
Copy link
Copy Markdown
Member

@tianon tianon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@thaJeztah
Copy link
Copy Markdown
Member Author

Windows 2022 failure is unrelated (known flaky test); #43012

=== RUN   TestDockerSuite/TestSlowStdinClosing/0
    docker_cli_run_test.go:4165: d:\CI\PR-43463\10\binary\docker.exe: Error response from daemon: failed to create shim task: open \\.\pipe\containerd-588a1f287c5980794c7b99e7c997b2949137ae811a72e1cef75dd971934d3e91-init-stdin: The system cannot find the file specified.: not found.
        
    docker_cli_run_test.go:4174: assertion failed: error is not nil: exit status 127
        --- FAIL: TestDockerSuite/TestSlowStdinClosing/0 (0.81s)

@thaJeztah thaJeztah merged commit bca8d9f into moby:master Apr 11, 2022
@thaJeztah thaJeztah deleted the httputils_readjson branch April 11, 2022 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants