fix: preserve request body in debug transport#671
Merged
Conversation
The debugTransport.RoundTrip method used req.Clone() to create a copy for debug logging, but Clone() performs a shallow copy — the Body io.ReadCloser is shared between the original and clone. When httputil.DumpRequestOut read the clone's body for logging, it drained the original request's body too. The subsequent RoundTrip then sent a request with an empty body but the original Content-Length header, causing CloudFront to reject it with a 400 error. Fix: read the body bytes upfront and create independent bytes.Reader instances for both the debug dump and the real request.
mcncl
reviewed
Mar 2, 2026
mcncl
approved these changes
Mar 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The
--debugflag was causing a 400 error from CloudFront, rather than giving me any debug output:The debugTransport.RoundTrip method used req.Clone() to create a copy for debug logging, but Clone() performs a shallow copy — the Body io.ReadCloser is shared between the original and clone. When httputil.DumpRequestOut read the clone's body for logging, it drained the original request's body too. The subsequent RoundTrip then sent a request with an empty body but the original Content-Length header, causing CloudFront to reject it with a 400 error.
Fix: Read the body bytes into memory once, then create independent
bytes.Readerinstances for both the debug dump and the real request. This ensures the body is fully available for both logging and the actual HTTP call.Testing
go test ./...)go fmt ./...)Disclosures / Credits
100% Claude. I noticed the issue and couldn't figure out what was going on. While debugging with Claude, it just went ahead and produced a fix. I verified that it works, it's formatted, and tests pass. I also asked it to go back and check that its changes conform to the general coding style of the repo. Then I got it to give me sort of a "Go newbie" explanation of what was going on in the bug - so as I understand it, we were losing the request body when we logged it to console in the debug output, and thus sending a zero-byte body in the request (only impacting commands that HAVE request a body, like
createwhere I stumbled on it).