You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When I try to have postForm automatically serialize a Blob in Node.js, it fails with the error message "Blob is not supported. Use a Buffer instead." I dug into it a bit, and it seems the culprit is a combination of things.
To Reproduce
Install the latest version of Node.js (at the time of writing: v21.7.3) and
Run a server that accepts file uploads at POST /api/upload (or whatever endpoint you'd like)
Have an image file in the path /tmp/image.jpg (or wherever you'd like)
postForm serializes the object containing the Blob as FormData and uploads it successfully
Axios Version
1.6.8
Adapter Version
No response
Browser
Node.js
Browser Version
v21.7.3
Node.js Version
v21.7.3
OS
macOS 14.4.1
Additional Library Versions
N/A
Additional context/Screenshots
On lib/helpers/toFormData.js:92, formData gets instantiated as PlatformFormData, which comes from the form-data package. This probably shouldn't happen, since Node.js has its own built-in FormData. I'd suggest swapping the order of that || statement to have any environment's built-in FormData take precedence.
There's a long-standing bug in form-data, form-data/form-data#396, wherein FormData[Symbol.toStringTag] is undefined. FormData[Symbol.iterator] is also undefined, but that's not covered in the issue. However, it is relevant here. The function isSpecCompliantForm (lib/utils.js:632) uses these to check whether whatever's getting passed in (thing) is indeed an instance of FormData. I'd suggest doing that a different way, such as using instanceof.
What does all this have to do with Blob? Well, for some reason that's beyond me, in toFormData, isSpecCompliantForm is tied to useBlob (lib/helpers/toFormData.js:110), the boolean that determines whether or not Blob is supported. In fact Blob is supported, by virtue of the fact that _Blob is defined in the previous line. I'd suggest decoupling these expressions, since bundling together FormData validation and Blob validation is too complex for one boolean, especially when the name of that boolean only references one of them. It unnecessarily breaks Blob support based on a bug in a third-party implementation of FormData—which, as you'll recall from earlier, we probably shouldn't even prefer to use in the first place.
Another question that comes to mind is: why do we even need to validate FormData at all here? Since we're already preferring a specific version of a third-party implementation of FormData, I think we can safely assume that what we have on our hands is actually a spec-compliant FormData (except, of course, for the finer details of Symbol.toStringTag where form-data differs from FormData). The only reason I can think of to validate FormData is if (as we should) we preferred to use the environment's built-in FormData, which might differ between environments. And doing that would actually fix this bug altogether.
The text was updated successfully, but these errors were encountered:
Axios supports Node v12 and above, so we can't just go the easy way and use the latest built-ins but have to support different formData implementations, as Axios is designed to be as flexible as possible.
In Axios 1.x, form-data is the default implementation. It does not support Blobs, but Streams and Buffers and doesn't follow web specs. Before version 2.x, it is not possible to change the usage priority of the FormData implementations without introducing breaking changes. And most likely even in the next major version, form-data support will still be relevant, because a lot of educational materials and codebases use it.
So for now you can either use streams/buffers in the context of the form-data module
Describe the bug
When I try to have
postForm
automatically serialize aBlob
in Node.js, it fails with the error message"Blob is not supported. Use a Buffer instead."
I dug into it a bit, and it seems the culprit is a combination of things.To Reproduce
POST /api/upload
(or whatever endpoint you'd like)/tmp/image.jpg
(or wherever you'd like)Code snippet
Expected behavior
postForm
serializes the object containing theBlob
asFormData
and uploads it successfullyAxios Version
1.6.8
Adapter Version
No response
Browser
Node.js
Browser Version
v21.7.3
Node.js Version
v21.7.3
OS
macOS 14.4.1
Additional Library Versions
Additional context/Screenshots
On lib/helpers/toFormData.js:92,
formData
gets instantiated asPlatformFormData
, which comes from theform-data
package. This probably shouldn't happen, since Node.js has its own built-inFormData
. I'd suggest swapping the order of that||
statement to have any environment's built-inFormData
take precedence.There's a long-standing bug in
form-data
, form-data/form-data#396, whereinFormData[Symbol.toStringTag]
isundefined
.FormData[Symbol.iterator]
is alsoundefined
, but that's not covered in the issue. However, it is relevant here. The functionisSpecCompliantForm
(lib/utils.js:632) uses these to check whether whatever's getting passed in (thing
) is indeed an instance ofFormData
. I'd suggest doing that a different way, such as usinginstanceof
.What does all this have to do with
Blob
? Well, for some reason that's beyond me, intoFormData
,isSpecCompliantForm
is tied touseBlob
(lib/helpers/toFormData.js:110), the boolean that determines whether or notBlob
is supported. In factBlob
is supported, by virtue of the fact that_Blob
is defined in the previous line. I'd suggest decoupling these expressions, since bundling togetherFormData
validation andBlob
validation is too complex for one boolean, especially when the name of that boolean only references one of them. It unnecessarily breaksBlob
support based on a bug in a third-party implementation ofFormData
—which, as you'll recall from earlier, we probably shouldn't even prefer to use in the first place.Another question that comes to mind is: why do we even need to validate
FormData
at all here? Since we're already preferring a specific version of a third-party implementation ofFormData
, I think we can safely assume that what we have on our hands is actually a spec-compliantFormData
(except, of course, for the finer details ofSymbol.toStringTag
whereform-data
differs fromFormData
). The only reason I can think of to validateFormData
is if (as we should) we preferred to use the environment's built-inFormData
, which might differ between environments. And doing that would actually fix this bug altogether.The text was updated successfully, but these errors were encountered: