Skip to content

*: fix request body not rewindable when forwarding HTTP requests#10589

Open
iosmanthus wants to merge 2 commits intotikv:masterfrom
iosmanthus:iosmanthus/fix-cannot-rewind-body
Open

*: fix request body not rewindable when forwarding HTTP requests#10589
iosmanthus wants to merge 2 commits intotikv:masterfrom
iosmanthus:iosmanthus/fix-cannot-rewind-body

Conversation

@iosmanthus
Copy link
Copy Markdown
Member

@iosmanthus iosmanthus commented Apr 9, 2026

What problem does this PR solve?

Issue Number: close #10590

When audit or rate-limit middleware is enabled, requestutil.getBodyParam
replaces r.Body with io.NopCloser(bytes.NewBuffer(buf)) without wiring
up r.GetBody. A request that originally had http.NoBody ends up with a
non-nil body reader and no rewind function.

When such a request is forwarded by customReverseProxies via
http.Client.Do, Go's Transport may need to retry on a new connection
(stale keep-alive, HTTP/2 GOAWAY). The Transport probes the body
(didRead=true) and on retry cannot rewind because GetBody is nil,
failing the forward with:

net/http: cannot rewind body after connection loss

What is changed and how does it work?

  • Add apiutil.EnsureRewindableBody(r) helper. It is a no-op when the body
    is nil, http.NoBody, or r.GetBody is already set. Otherwise it
    drains the body once, restores http.NoBody semantics for empty payloads
    (so Transport.outgoingLength returns 0 and no body probing happens),
    wires r.GetBody to return a fresh reader over the buffered bytes, and
    sets r.ContentLength to the exact length.
  • Use the helper in customReverseProxies.ServeHTTP before calling
    http.Client.Do, so any forwarded request is rewindable.
  • Refactor requestutil.getBodyParam to reuse the helper, then read the
    cached body via r.GetBody() for audit logging. This fixes the root
    cause while keeping existing audit behavior.
  • Add TestEnsureRewindableBody covering nil/NoBody/existing-GetBody
    no-op paths, empty-body NoBody restoration, non-empty rewindability
    across multiple GetBody() invocations, and read-error propagation.
*: fix request body not rewindable when forwarding HTTP requests

When audit or rate-limit middleware is enabled, getBodyParam replaces
r.Body without setting r.GetBody. Forwarding such a request through
customReverseProxies via http.Client.Do fails on retry with
"net/http: cannot rewind body after connection loss". Introduce
apiutil.EnsureRewindableBody and use it on the forwarding path and in
getBodyParam to make the body safely rewindable.

Check List

Tests

  • Unit test

Side effects

  • Possible performance regression (body is buffered into memory once per
    forwarded request that has a body — same as the pre-existing audit path)

Related changes

  • Need to cherry-pick to the release branch

Release note

Fix "net/http: cannot rewind body after connection loss" when a PD
follower forwards HTTP requests to the leader with audit or rate-limit
middleware enabled.

Summary by CodeRabbit

  • Bug Fixes

    • Improved HTTP request body handling to ensure request bodies can be reliably read and re-read throughout the request lifecycle.
  • Tests

    • Added comprehensive test coverage for request body rewindability across various scenarios.

@ti-chi-bot ti-chi-bot bot added do-not-merge/needs-linked-issue dco-signoff: yes Indicates the PR's author has signed the dco. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Apr 9, 2026
@ti-chi-bot
Copy link
Copy Markdown
Contributor

ti-chi-bot bot commented Apr 9, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign rleungx for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: db1afb9a-8fd0-4a6d-90c9-01c2359d754a

📥 Commits

Reviewing files that changed from the base of the PR and between c71d947 and 6a947d2.

📒 Files selected for processing (1)
  • pkg/utils/apiutil/apiutil_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/utils/apiutil/apiutil_test.go

📝 Walkthrough

Walkthrough

Introduced EnsureRewindableBody(*http.Request) error to buffer and make request bodies rewindable, invoked by the custom reverse-proxy before forwarding; updated body-reading utility to use r.GetBody() and return empty when rewindability isn't available; added tests covering nil, NoBody, empty, non-empty, and error cases.

Changes

Cohort / File(s) Summary
Request Body Rewindability (implementation)
pkg/utils/apiutil/apiutil.go
Added EnsureRewindableBody(r *http.Request) error that buffers non-nil bodies into memory, sets r.GetBody to return fresh readers, updates r.ContentLength, preserves http.NoBody semantics for zero-length bodies, and is called at the start of customReverseProxies.ServeHTTP (returns 500 if it fails).
Request Body Rewindability (tests)
pkg/utils/apiutil/apiutil_test.go
Added TestEnsureRewindableBody and helpers to validate behavior for nil, http.NoBody, empty, and non-empty bodies; checks original body closing, ContentLength, GetBody presence, repeatable independent readers, and propagation of underlying read errors.
Body Parameter Extraction
pkg/utils/requestutil/request_info.go
getBodyParam now requires r.GetBody and returns "" if body is unavailable or cannot be made rewindable; it reads body content via r.GetBody() (closing the returned reader) instead of consuming r.Body directly.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ReverseProxy
  participant APIUtil as EnsureRewindableBody
  participant Backend

  Client->>ReverseProxy: HTTP request (with possible Body)
  ReverseProxy->>APIUtil: EnsureRewindableBody(r)
  alt EnsureRewindableBody succeeds
    APIUtil-->>ReverseProxy: nil (r.GetBody set / Body rewindable)
    ReverseProxy->>Backend: Forward request (Transport may call r.GetBody on retry)
    Backend-->>ReverseProxy: Response
    ReverseProxy-->>Client: Response
  else EnsureRewindableBody fails
    APIUtil-->>ReverseProxy: error
    ReverseProxy-->>Client: 500 Internal Server Error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hid the crumbs in memory tight,

So proxies can hop back and retry at night.
No lost reads, no sudden sob,
Each GetBody serves a fresh small hob —
Buffer, rewind, and all feels right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and concisely describes the primary change: fixing request body rewindability when forwarding HTTP requests.
Description check ✅ Passed The description fully addresses the template requirements: identifies the issue (#10590), explains the problem and solution, includes a commit message, specifies unit tests, notes side effects, and provides a release note.
Linked Issues check ✅ Passed The code changes directly address issue #10590 by introducing EnsureRewindableBody to guarantee request rewindability before forwarding, preventing the 'cannot rewind body after connection loss' error on connection retry.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the rewindable body issue: the new EnsureRewindableBody helper, its integration into customReverseProxies and getBodyParam, and comprehensive test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ti-chi-bot ti-chi-bot bot added the size/S Denotes a PR that changes 10-29 lines, ignoring generated files. label Apr 9, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/utils/apiutil/apiutil.go (1)

492-503: Bound request-body buffering to avoid unbounded allocations.

This path reads the full body into memory for every forwarded request with GetBody == nil. Add a hard cap and return 413 when exceeded to avoid memory pressure under large payloads.

💡 Proposed bounded-buffering change
+const maxRewindBodyBytes int64 = 8 << 20 // 8 MiB

 func (p *customReverseProxies) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   if r.Body != nil && r.Body != http.NoBody && r.GetBody == nil {
-    bodyBytes, err := io.ReadAll(r.Body)
+    lr := &io.LimitedReader{R: r.Body, N: maxRewindBodyBytes + 1}
+    bodyBytes, err := io.ReadAll(lr)
     r.Body.Close()
     if err != nil {
       log.Error("failed to read request body", zap.Error(err))
       http.Error(w, err.Error(), http.StatusInternalServerError)
       return
     }
+    if int64(len(bodyBytes)) > maxRewindBodyBytes {
+      http.Error(w, "request body too large", http.StatusRequestEntityTooLarge)
+      return
+    }
     r.Body = io.NopCloser(bytes.NewReader(bodyBytes))
     r.GetBody = func() (io.ReadCloser, error) {
       return io.NopCloser(bytes.NewReader(bodyBytes)), nil
     }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/utils/apiutil/apiutil.go` around lines 492 - 503, The code
unconditionally reads the entire request body into memory when r.GetBody == nil;
change that to use a bounded read (e.g., io.LimitedReader or similar) with a
configurable MAX_BODY_BYTES and if the body exceeds the limit return
http.Error(w, "request entity too large", http.StatusRequestEntityTooLarge)
(413). Ensure you still close the original r.Body, set r.Body to a new
io.NopCloser over the buffered bytes and implement r.GetBody to return a fresh
reader for the same buffered bytes (use the truncated/allowed bytes only), and
preserve existing error logging via log.Error when reading fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/utils/apiutil/apiutil.go`:
- Around line 495-498: Read handler currently logs the internal error via
log.Error but writes err.Error() to the response using http.Error(w,
err.Error(), ...); change this to return a stable client-facing message and
appropriate status code (e.g., http.Error(w, "invalid request body",
http.StatusBadRequest)) while keeping the detailed error only in the server log
(log.Error(..., zap.Error(err))). Update the branch that checks err (the block
using log.Error, http.Error, w, err) to not expose err.Error() to clients and
ensure payload validation is applied before processing.

---

Nitpick comments:
In `@pkg/utils/apiutil/apiutil.go`:
- Around line 492-503: The code unconditionally reads the entire request body
into memory when r.GetBody == nil; change that to use a bounded read (e.g.,
io.LimitedReader or similar) with a configurable MAX_BODY_BYTES and if the body
exceeds the limit return http.Error(w, "request entity too large",
http.StatusRequestEntityTooLarge) (413). Ensure you still close the original
r.Body, set r.Body to a new io.NopCloser over the buffered bytes and implement
r.GetBody to return a fresh reader for the same buffered bytes (use the
truncated/allowed bytes only), and preserve existing error logging via log.Error
when reading fails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fdde20d7-c34d-4392-9c95-5d37062e55f8

📥 Commits

Reviewing files that changed from the base of the PR and between b21a183 and 98ace34.

📒 Files selected for processing (2)
  • pkg/utils/apiutil/apiutil.go
  • pkg/utils/requestutil/request_info.go

Comment on lines +495 to +498
if err != nil {
log.Error("failed to read request body", zap.Error(err))
http.Error(w, err.Error(), http.StatusInternalServerError)
return
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid returning raw internal error text to clients.

Returning err.Error() directly can expose internal details; use a stable message and an appropriate client-facing status code.

🔧 Proposed response handling adjustment
   if err != nil {
     log.Error("failed to read request body", zap.Error(err))
-    http.Error(w, err.Error(), http.StatusInternalServerError)
+    http.Error(w, "failed to read request body", http.StatusBadRequest)
     return
   }
As per coding guidelines, "HTTP handlers must validate payloads and return proper status codes; avoid panics".
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if err != nil {
log.Error("failed to read request body", zap.Error(err))
http.Error(w, err.Error(), http.StatusInternalServerError)
return
if err != nil {
log.Error("failed to read request body", zap.Error(err))
http.Error(w, "failed to read request body", http.StatusBadRequest)
return
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/utils/apiutil/apiutil.go` around lines 495 - 498, Read handler currently
logs the internal error via log.Error but writes err.Error() to the response
using http.Error(w, err.Error(), ...); change this to return a stable
client-facing message and appropriate status code (e.g., http.Error(w, "invalid
request body", http.StatusBadRequest)) while keeping the detailed error only in
the server log (log.Error(..., zap.Error(err))). Update the branch that checks
err (the block using log.Error, http.Error, w, err) to not expose err.Error() to
clients and ensure payload validation is applied before processing.

Copy link
Copy Markdown
Member

@JmPotato JmPotato left a comment

Choose a reason for hiding this comment

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

Could you add a corresponding test?

@iosmanthus
Copy link
Copy Markdown
Member Author

Could you add a corresponding test?

Sure!

@iosmanthus iosmanthus force-pushed the iosmanthus/fix-cannot-rewind-body branch from 98ace34 to c85ce09 Compare April 9, 2026 10:04
@ti-chi-bot ti-chi-bot bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels Apr 9, 2026
When audit or rate-limit middleware is enabled, `getBodyParam` replaces
`r.Body` with an `io.NopCloser` wrapping a `bytes.Buffer` but does not
set `r.GetBody`. This turns `http.NoBody` into a non-nil, non-NoBody
reader without a rewind function.

Later, when `customReverseProxies` forwards the request via
`http.Client.Do`, Go's transport may need to retry on a new connection
(e.g. stale keep-alive, HTTP/2 GOAWAY). The transport probes the body
(setting didRead=true), but cannot rewind it because `GetBody` is nil,
resulting in: "net/http: cannot rewind body after connection loss".

This commit fixes both the root cause and adds a defensive guard:

1. `getBodyParam`: skip `http.NoBody`, and set both `Body` and `GetBody`
   when replacing the body so that the transport can rewind on retry.
2. `customReverseProxies.ServeHTTP`: before forwarding, ensure any
   non-nil body without `GetBody` is made rewindable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@iosmanthus iosmanthus force-pushed the iosmanthus/fix-cannot-rewind-body branch from c85ce09 to c71d947 Compare April 9, 2026 10:07
@ti-chi-bot ti-chi-bot bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Apr 9, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
pkg/utils/apiutil/apiutil.go (1)

525-528: ⚠️ Potential issue | 🟠 Major

Do not expose raw internal errors in HTTP responses.

Line [527] returns err.Error() to clients, which can leak internal details. Return a stable message and a client-appropriate status instead.

🔧 Suggested response handling
 	if err := EnsureRewindableBody(r); err != nil {
 		log.Error("failed to read request body", zap.Error(err))
-		http.Error(w, err.Error(), http.StatusInternalServerError)
+		http.Error(w, "invalid request body", http.StatusBadRequest)
 		return
 	}

As per coding guidelines, "HTTP handlers must validate payloads and return proper status codes; avoid panics".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/utils/apiutil/apiutil.go` around lines 525 - 528, The handler currently
returns raw err.Error() to clients after calling EnsureRewindableBody, which can
leak internals; update the response to log the detailed error with
log.Error(zap.Error(err)) but send a stable, client-safe message instead (e.g.,
http.Error(w, "failed to read request body", http.StatusBadRequest) or
http.StatusInternalServerError as appropriate for the failure type). Modify the
code around the EnsureRewindableBody call in apiutil.go so it does not return
err.Error() to the client but uses a fixed message and appropriate status while
preserving the detailed zap.Error(err) in server logs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/utils/apiutil/apiutil.go`:
- Around line 501-521: The code that calls io.ReadAll(r.Body) must enforce a
max-body-size to prevent OOM: change the read to use a bounded reader (e.g.,
buf, err := io.ReadAll(io.LimitReader(r.Body, maxBodySize+1))) and check if
len(buf) > maxBodySize then return a specific sentinel error (e.g.,
ErrRequestBodyTooLarge) instead of buffering unbounded data; restore
r.Body/GetBody from the buffered bytes only when within the limit. In the
ServeHTTP reverse proxy handler, do not propagate err.Error() to clients—handle
ErrRequestBodyTooLarge by responding with a generic 413 Payload Too Large
message (or use http.MaxBytesReader at the handler boundary as an alternative)
and for other errors return a sanitized message. Ensure the symbols referenced
are the io.ReadAll call and r.Body / r.GetBody assignments and the ServeHTTP
reverse proxy handler.

---

Duplicate comments:
In `@pkg/utils/apiutil/apiutil.go`:
- Around line 525-528: The handler currently returns raw err.Error() to clients
after calling EnsureRewindableBody, which can leak internals; update the
response to log the detailed error with log.Error(zap.Error(err)) but send a
stable, client-safe message instead (e.g., http.Error(w, "failed to read request
body", http.StatusBadRequest) or http.StatusInternalServerError as appropriate
for the failure type). Modify the code around the EnsureRewindableBody call in
apiutil.go so it does not return err.Error() to the client but uses a fixed
message and appropriate status while preserving the detailed zap.Error(err) in
server logs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bf78e3d4-8d96-4aa6-8898-f7d82721eee8

📥 Commits

Reviewing files that changed from the base of the PR and between 98ace34 and c71d947.

📒 Files selected for processing (3)
  • pkg/utils/apiutil/apiutil.go
  • pkg/utils/apiutil/apiutil_test.go
  • pkg/utils/requestutil/request_info.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/utils/requestutil/request_info.go

Comment on lines +501 to +521
buf, err := io.ReadAll(r.Body)
_ = r.Body.Close()
if err != nil {
return err
}
// Restore NoBody semantics for empty payloads so that Transport's
// outgoingLength returns 0 and no body probing happens.
if len(buf) == 0 {
r.Body = http.NoBody
r.GetBody = func() (io.ReadCloser, error) { return http.NoBody, nil }
r.ContentLength = 0
return nil
}
r.Body = io.NopCloser(bytes.NewReader(buf))
r.GetBody = func() (io.ReadCloser, error) {
return io.NopCloser(bytes.NewReader(buf)), nil
}
// We now know the exact length; set it so the transport can pick
// Content-Length framing over chunked encoding when forwarding.
r.ContentLength = int64(len(buf))
return nil
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current helper has unbounded body buffering and where it is used.
rg -n 'func EnsureRewindableBody|io.ReadAll\(r.Body\)|LimitedReader|maxRewindableBodyBytes' pkg/utils/apiutil/apiutil.go
rg -n 'EnsureRewindableBody\(' pkg/utils/apiutil/apiutil.go pkg/utils/requestutil/request_info.go

Repository: tikv/pd

Length of output: 425


🏁 Script executed:

# Examine the ServeHTTP handler context where EnsureRewindableBody is called
sed -n '520,535p' pkg/utils/apiutil/apiutil.go

# Check for any request size limit configuration in the server setup
rg -n 'MaxHeaderBytes|ContentLength|MaxBytesReader|LimitedReader|maxBody|size.*limit' pkg/utils/apiutil/ pkg/utils/requestutil/ -A 2 -B 2 | head -50

# Check the request_info.go usage context
sed -n '65,85p' pkg/utils/requestutil/request_info.go

Repository: tikv/pd

Length of output: 2553


🏁 Script executed:

# Check for server configuration and request size limits
rg -n 'http\.Server|MaxHeaderBytes|MaxBytesReader|ListenAndServe|NewServer' pkg/ cmd/ --type go -B 2 -A 3 | head -60

# Check if there's any middleware that validates request size
rg -n 'ContentLength.*<|request.*size|body.*limit|ReadLimitCloser' pkg/ cmd/ --type go | head -20

# Check what the error message would look like
sed -n '497,530p' pkg/utils/apiutil/apiutil.go

Repository: tikv/pd

Length of output: 4467


Add a max body-size guard before buffering.

Line 501 reads the full request body into memory with no upper bound. When called in the ServeHTTP reverse proxy handler (line 525), this creates a memory-exhaustion vector—an attacker can send large payloads to exhaust memory and trigger OOM without any server-side size limit configured.

Additionally, line 528 exposes the raw error message to the client via http.Error(w, err.Error(), ...), which should not leak internal details.

🔧 Suggested fix
+const maxRewindableBodyBytes = 8 << 20 // 8 MiB, tune as needed
+
 func EnsureRewindableBody(r *http.Request) error {
 	if r.Body == nil || r.Body == http.NoBody || r.GetBody != nil {
 		return nil
 	}
-	buf, err := io.ReadAll(r.Body)
+	if r.ContentLength > maxRewindableBodyBytes {
+		_ = r.Body.Close()
+		return errors.Errorf("request body too large: %d", r.ContentLength)
+	}
+	lr := &io.LimitedReader{R: r.Body, N: maxRewindableBodyBytes + 1}
+	buf, err := io.ReadAll(lr)
 	_ = r.Body.Close()
 	if err != nil {
 		return err
 	}
+	if int64(len(buf)) > maxRewindableBodyBytes {
+		return errors.Errorf("request body too large")
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/utils/apiutil/apiutil.go` around lines 501 - 521, The code that calls
io.ReadAll(r.Body) must enforce a max-body-size to prevent OOM: change the read
to use a bounded reader (e.g., buf, err := io.ReadAll(io.LimitReader(r.Body,
maxBodySize+1))) and check if len(buf) > maxBodySize then return a specific
sentinel error (e.g., ErrRequestBodyTooLarge) instead of buffering unbounded
data; restore r.Body/GetBody from the buffered bytes only when within the limit.
In the ServeHTTP reverse proxy handler, do not propagate err.Error() to
clients—handle ErrRequestBodyTooLarge by responding with a generic 413 Payload
Too Large message (or use http.MaxBytesReader at the handler boundary as an
alternative) and for other errors return a sanitized message. Ensure the symbols
referenced are the io.ReadAll call and r.Body / r.GetBody assignments and the
ServeHTTP reverse proxy handler.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 9, 2026

Codecov Report

❌ Patch coverage is 78.57143% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.97%. Comparing base (b21a183) to head (6a947d2).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff            @@
##           master   #10589    +/-   ##
========================================
  Coverage   78.96%   78.97%            
========================================
  Files         532      532            
  Lines       71883    71987   +104     
========================================
+ Hits        56766    56852    +86     
- Misses      11093    11109    +16     
- Partials     4024     4026     +2     
Flag Coverage Δ
unittests 78.97% <78.57%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ti-chi-bot ti-chi-bot bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. do-not-merge/needs-triage-completed and removed do-not-merge/needs-linked-issue do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels Apr 9, 2026
Move `require.New(t)` into each subtest so that failures are attributed
to the correct sub-`*testing.T`, and apply minor lint fixes (unused
param, intrange).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: iosmanthus <myosmanthustree@gmail.com>
@iosmanthus
Copy link
Copy Markdown
Member Author

/retest

@ti-chi-bot
Copy link
Copy Markdown
Contributor

ti-chi-bot bot commented Apr 10, 2026

@iosmanthus: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-error-log-review 6a947d2 link true /test pull-error-log-review
pull-unit-test-next-gen-2 6a947d2 link true /test pull-unit-test-next-gen-2
pull-integration-realcluster-test 6a947d2 link true /test pull-integration-realcluster-test

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has signed the dco. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

*: forwarding HTTP requests can fail with "net/http: cannot rewind body after connection loss"

2 participants