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

Skip to content

Drop forced bare multipart/form-data placeholder header in postForm/putForm/patchForm (breaks RN Android) #10886

Description

@jasonsaayman

Tracking issue for a maintainer to pick up. Splits the legitimate fix out of #7243 so the actual bug from #6968 can land cleanly.

Background

axios.postForm / putForm / patchForm in lib/core/Axios.js currently force a placeholder header on the overlay config:

headers: isForm ? { 'Content-Type': 'multipart/form-data' } : {}

The intent is to let the adapter rewrite this with a real boundary later. That works on:

  • The browser XHR adapter (the platform appends the boundary).
  • The Node HTTP adapter via the form-data package (getHeaders() overwrites it).
  • The fetch adapter / spec-compliant FormData via formDataToStream (boundary attached).

It does not work on React Native Android. RN is neither hasStandardBrowserEnv (axios deliberately excludes RN in resolveConfig) nor does it use form-data. The bare placeholder reaches the wire untouched, and Android's networking layer rejects multipart/form-data without a boundary. iOS is more permissive, which is why this only reproduces on Android.

Original report: #6968. Attempted fix: #7243 (closed — see review for why that diff isn't the right shape).

Proposed fix

In lib/core/Axios.js, in the post/put/patch helper factory, drop the placeholder entirely:

return this.request(mergeConfig(config || {}, {
  method,
  url,
  data
}));

(Or headers: {} if we'd rather be explicit.) config.headers is already merged in by mergeConfig(config || {}, …) — the second argument is the overlay, not the source — so anything the caller passes still flows through. No placeholder, nothing to overwrite, no Android breakage.

The toFormData.js changes in #7243 should not be carried over:

  • Function('return this')() is eval in a different shape; trips CSP without unsafe-eval (most production browsers behind a CSP, several RN setups).
  • The precedence flip from PlatformFormData || FormData to runtimeFD || PlatformFormData silently breaks 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() gets an object without them.
  • 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 resolves to the RN runtime's FormData.

Tests required

  • postForm / putForm / patchForm no longer emit a bare Content-Type: multipart/form-data 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.
  • Caller-provided Content-Type on the request config is preserved through the FormData helpers.

Acceptance

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions