Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix: remove forced multipart header to fix Android postForm/patchForm…#7243

Closed
neel3o115 wants to merge 1 commit into
axios:v1.xfrom
neel3o115:fix/rn-android-postform
Closed

fix: remove forced multipart header to fix Android postForm/patchForm…#7243
neel3o115 wants to merge 1 commit into
axios:v1.xfrom
neel3o115:fix/rn-android-postform

Conversation

@neel3o115

@neel3o115 neel3o115 commented Nov 18, 2025

Copy link
Copy Markdown

This PR fixes a long-standing issue where axios.postForm, axios.putForm, and axios.patchForm fail on React Native Android with a Network Error.
The issue occurs because Axios forces a bare:
Content-Type: multipart/form-data
header without a boundary.
React Native Android requires a boundary (e.g. boundary=----RNFormBoundaryABC123).
When Axios overrides the header, React Native cannot append the boundary, causing the request to be malformed and immediately rejected.

iOS is more permissive, so it does not fail.

What This PR Changes:-

  1. Removes the forced 'Content-Type': 'multipart/form-data' header
  2. Preserves user-provided headers
  3. Does not affect existing behavior on:

iOS React Native (already worked)

Standard axios.post / axios.patch / axios.put (not using FormData helpers)

Technical Summary

Before (broken on Android):
headers: { 'Content-Type': 'multipart/form-data' }

After (correct):
headers: isForm ? (config?.headers || {}) : {}

This lets React Native generate:
Content-Type: multipart/form-data; boundary=----RNGeneratedBoundary123
which Android accepts.

Result:-

  • Android multipart uploads work
  • No more Network Error
  • No breaking changes
  • Fully backward-compatible

Fixes
#6968

@nidhishgajjar

This comment was marked as spam.

1 similar comment
@nidhishgajjar

This comment was marked as spam.

@jasonsaayman jasonsaayman added type::breaking The PR introduces breaking changes commit::fix labels Apr 28, 2026
@jasonsaayman jasonsaayman added priority::medium status::changes-requested A reviewer requested changes to the PR status::needs-rebase The PR requires a rebase and removed type::breaking The PR introduces breaking changes labels Apr 29, 2026

@jasonsaayman jasonsaayman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @neel3o115, and apologies on the wait. The diagnosis is right, Android's RN networking layer rejects bare multipart/form-data without a boundary, iOS doesn't, and the gap exists because RN is neither hasStandardBrowserEnv (axios deliberately excludes RN from that flag in resolveConfig) nor uses Node's form-data package. The placeholder header reaches the wire untouched on RN, and Android complains. Worth fixing.

Three asks before this can merge.

First, drop the toFormData.js changes. Function('return this')() is eval in a different shape — it trips CSP without unsafe-eval, which covers most production browsers behind a CSP and several RN setups. globalThis is universally available everywhere axios runs if global access were ever needed, but it isn't here. The precedence flip from PlatformFormData || FormData to runtimeFD || PlatformFormData is also a silent breakage on Node: Node 18+ has global FormData, so this picks the spec-compliant one over form-data, and any caller of axios.toFormData(obj) on Node who relied on .getHeaders() / .getLength() (documented form-data API) gets an object without them. And it isn't needed for the RN bug — RN bundlers resolve the browser field in package.json, so PlatformFormData already points at lib/platform/browser/classes/FormData.js, which is typeof FormData !== 'undefined' ? FormData : null. In RN, that's the runtime's FormData.

Second, tighten the Axios.js change. What you have:

  headers: isForm
    ? (config && config.headers ? config.headers : {})
    : {},

config.headers is already merged in by mergeConfig(config || {}, …) — the second argument is the overlay, not the source. Re-passing config.headers is either a no-op or runs the header merge strategy twice. The minimal version is headers: {}, or drop the headers key from the overlay entirely. Same effect: no placeholder is forced, anything in config.headers still flows through normally.

Third, add tests. At minimum: postForm (and put/patch) no longer emit the bare placeholder; Node form-data path still ends up with Content-Type: multipart/form-data; boundary=… via getHeaders(); spec-compliant FormData path through the http adapter still gets a boundary via formDataToStream.

@jasonsaayman

Copy link
Copy Markdown
Member

Thanks, @neel3o115. Going to close this one, but the underlying bug is real and worth fixing. I've split it into #10886 so it can be picked up cleanly.

If you take another stab at it, please ping me to review.

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

Labels

status::changes-requested A reviewer requested changes to the PR status::needs-rebase The PR requires a rebase

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants