Fix (android): show payload preview for FormData and one-shot uploads in DevTools (#55764)#56742
Open
HarshitMadhav wants to merge 2 commits into
Open
Fix (android): show payload preview for FormData and one-shot uploads in DevTools (#55764)#56742HarshitMadhav wants to merge 2 commits into
HarshitMadhav wants to merge 2 commits into
Conversation
1981a55 to
c099d9d
Compare
huntie
reviewed
May 13, 2026
Member
huntie
left a comment
There was a problem hiding this comment.
Looks strong, thank you!
Would you be able to build and test this end-to-end for the two new cases, ideally with a screenshot in RNDT? Important to validate this works at runtime without crashes, as it's been a sensitive code path before (see also my test suggestion) 🙏🏻
| Path | Trigger in DevTools |
|---|---|
| Single one-shot body → [Binary data, N bytes] | POST a single-file RequestBody from a URI |
| MultipartBody with one-shot part → synthesised envelope | POST a FormData with a file via fetch |
| assertThat(preview).contains("name=\"file\"") | ||
| assertThat(preview).contains("filename=\"photo.jpg\"") | ||
| assertThat(preview).contains("[Binary data, 2048 bytes]") | ||
| assertThat(preview).doesNotContain("[Preview unavailable]") |
Member
There was a problem hiding this comment.
Could we add an assertion that the underlying stream isn't consumed? The current tests check output shape, but a regression that drops the isOneShot() guard inside previewMultipartWithBinaryParts could still pass them. Something like:
val stream = ByteArrayInputStream(fileBytes)
val streamingPart =
RequestBodyUtil.create(MediaType.parse("application/octet-stream"), stream)
// ...build + call getRequestBodyPreview...
assertThat(stream.available()).isEqualTo(fileBytes.size)
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:
Follow-up to #56406. After that PR landed, NetworkEventUtil.getRequestBodyPreview still returns the literal string "[Preview unavailable]" in two cases:
The top-level RequestBody.isOneShot() is true (e.g. a single URI/file upload).
The body is a MultipartBody whose parts include any one-shot stream (the common case for FormData with files on Android).
Both branches exist for a good reason — calling writeTo() on a one-shot stream would drain it and break the real upload. This PR keeps that invariant but replaces the two return sites with structured previews:
Single one-shot body → [Binary data, N bytes] (or [Binary data] if contentLength() is unknown).
MultipartBody with one-shot parts → a multipart envelope using the request's actual boundary, with text parts inlined and one-shot parts replaced by [Binary data, N bytes]. The result parses cleanly against the on-the-wire Content-Type: multipart/form-data; boundary=..., so DevTools renders it the same way it renders any other multipart payload.
Net result: issue #55764 (no payload preview for FormData / file uploads in the React Native DevTools Network tab) is closed, with no change to what gets sent on the wire.
Changelog:
NetworkEventUtil.kt: replace the two "[Preview unavailable]" returns with binaryPartLabel(body) and a new previewMultipartWithBinaryParts(body) helper. No change to the existing all-text path.
NetworkEventUtilTest.kt: 6 new tests covering null body, plain string body, ProgressRequestBody unwrapping, multipart with text parts, multipart with a file part, and a single one-shot body.
[ANDROID] [FIXED] - Show request body preview for FormData and file uploads in DevTools Network tab
Test Plan:
./gradlew :packages:react-native:ReactAndroid:testDebugUnitTest --tests "com.facebook.react.modules.network.*"— 16/16 pass in NetworkEventUtilTest, full network suite green.Manual: in RN-Tester debug build, POST a FormData with a file using fetch → DevTools Network → Payload tab now shows the multipart envelope with [Binary data, N bytes] instead of [Preview unavailable].
Manual: POST a single-file RequestBody from a URI → preview now shows [Binary data, N bytes].
Stream safety
The whole point of #56406's bail-outs was to avoid draining one-shot streams. This PR preserves that: it never calls writeTo() on a body whose isOneShot() is true. The only RequestBody methods invoked on one-shot bodies are contentType() and contentLength(), both of which are pure getters per the OkHttp docs.
Refs #55764, follows up on #56406.