Fix: binary request body corruption in TS→WS→Go transport#417
Open
Danny-Dasilva wants to merge 1 commit intomainfrom
Open
Fix: binary request body corruption in TS→WS→Go transport#417Danny-Dasilva wants to merge 1 commit intomainfrom
Danny-Dasilva wants to merge 1 commit intomainfrom
Conversation
When a binary body (Buffer/Uint8Array/ArrayBuffer) is passed to the TS client, route it through the existing `bodyBytes` field as base64. JSON cannot carry raw bytes: `JSON.stringify` emits bytes > 0x7F as \uXXXX escapes, Go's decoder stores them as runes, and they re-emit as UTF-8 (e.g. 0xDE → 0xC3 0x9E) — corrupting the request body. Go already has `Options.BodyBytes []byte` wired with priority over `Body` (cycletls/index.go:195,347,1418); `encoding/json` unmarshals base64 strings directly into []byte. The client just wasn't using it. - Expand `body` type to accept Buffer | Uint8Array | ArrayBuffer - Add explicit `bodyBytes` option for callers that want to be explicit - Auto-route binary `body` to `bodyBytes` in `sendRequest` - Plain string bodies remain unchanged (URLSearchParams / FormData / string paths untouched) - Add regression test covering Buffer, Uint8Array, explicit bodyBytes, all-256-byte-values round-trip, and string pass-through Verified against the user's httpbin.io repro — CycleTLS now returns the same base64 payload as `fetch`.
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.
Summary
When a binary body is passed via
options.body, the TS client callsJSON.stringify({requestId, options}). JSON cannot carry raw bytes:JSON.stringifyemits bytes > 0x7F as\uXXXXescapes, Go's decoder stores them as runes, and when Go writes them back to an HTTP request body they re-emit as UTF-8 (e.g.0xDE→0xC3 0x9E). The result: upstream servers receive a corrupted payload.The Go server already has
Options.BodyBytes []bytewired as the priority branch (cycletls/index.go:195,347,1418), andencoding/jsonunmarshals a base64 string directly into[]byte. The TS client simply wasn't using it.This PR:
bodytype to acceptBuffer | Uint8Array | ArrayBufferbodyBytesoptionbodyBytesURLSearchParams/FormDatapaths untouchedReproduction (from the bug report)
Before:
data:application/octet-stream;base64,w57CrcK-w6_Cq8ONw68SNFY=(UTF-8 mangled)After:
data:application/octet-stream;base64,3q2-76vN7xI0Vg==(matches nativefetch)Test plan
tests/binary-body-roundtrip.test.tswith 5 cases (local HTTP echo server, byte-for-byte verification):bodyBytesbodyBytesoptionbodytests/urlencoded.test.tsandtests/multipartFormData.test.tspass unchangedhttps://httpbin.io/postreproduces the original bug and confirms the fixNotes
BodyByteswas already there.🤖 Generated with Claude Code