Skip to content

fix(rest): enforce request body limits while reading - #5871

Closed
leehainuo wants to merge 2 commits into
zeromicro:masterfrom
leehainuo:codex/fix-maxbytes-read-limit
Closed

leehainuo wants to merge 2 commits into
zeromicro:masterfrom
leehainuo:codex/fix-maxbytes-read-limit

Conversation

@leehainuo

@leehainuo leehainuo commented Nov 1, 2026 •

Copy link
Copy Markdown

MaxBytesHandler checks only ContentLength, so unknown-length requests can bypass a configured body limit. For example, with a limit of 8 bytes, a 16-byte JSON request can reach the handler and be parsed successfully.

Wrap accepted request bodies with http.MaxBytesReader to enforce the limit while reading. Keep the existing early rejection for known oversized requests and the disabled-limit behavior. In the default httpx.Error and httpx.ErrorCtx paths, map direct or wrapped *http.MaxBytesError values to HTTP 413. Custom error handlers keep their existing precedence.

Companion to #5815, following #5815 (comment). This PR can be reviewed independently and does not eagerly read or buffer the complete request body.

Regression coverage:

  • Known/unknown lengths, bodies within and exactly at the limit, and oversized bodies.
  • Real HTTP/1.1 chunked requests through httptest.NewServer, using dynamically allocated ports and checking the server's actual content length and transfer encoding.
  • Ordinary read-error propagation and handlers that do not read the request body.
  • Direct/wrapped size errors in each default HTTP error API, plus custom error-handler precedence. Tests follow the existing separate Error/ErrorCtx layout.

The JSON tests use jsonx.UnmarshalFromReader, the same decoder path used by the parser, so they do not depend on #5815. The two fixes were also tested together with a temporary Go overlay and real HTTP requests, including empty-body defaults and HTTP 413 for oversized chunked JSON.

Validation:

  • go test -mod=readonly -race ./rest/handler ./rest/httpx -count=1
  • go vet -mod=readonly ./rest/handler ./rest/httpx
  • go test -mod=readonly -race -coverprofile=coverage.txt -covermode=atomic ./... -skip '^TestRpcServer$' -timeout 3m
  • gofmt and git diff --check

The local root-module run skips only the unchanged zrpc/internal.TestRpcServer, whose fixed localhost:54321 port is occupied by an existing application. All remaining packages and tests passed. The earlier upstream Linux failure was in the unchanged gateway.TestHttpToHttp (listen tcp :45678: bind: address already in use); the relevant REST packages passed that run. The follow-up commit adds regression coverage and does not modify gateway tests or CI configuration.

Upstream CI on d1ef79d972dc350b66aacc0b7b392b7670e0c8e0 is now green: Go (Linux, Windows, and RPC generation), staticcheck, and CodeQL. The Linux run includes the full test suite without the local skip and a successful Codecov upload.

@codecov

codecov Bot commented Nov 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@leehainuo

Copy link
Copy Markdown
Author

Closing this PR because I am continuing the same fix from my new account, @hainuoli, in #5879. The replacement preserves both commits and links back to this PR for the original discussion and CI results. The companion JSON parsing fix continues in #5880 (replacing #5815). Please continue review on the replacement PRs.

@leehainuo leehainuo closed this Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants