ofetch
ofetch copied to clipboard
FormData support
Seems a good idea for using [object FormData] to append proper content-type (adding in short)
Originally posted by @pi0 in https://github.com/unjs/ohmyfetch/pull/36#discussion_r767707178
Other notes:
- validate formdata content or ensure we're not in browser environment to avoid setting header when sending files/blobs
Content-Dispositionheader
Very interested in gaining access to the Content-Disposition header. That is something we need for our project.
I did not know about Content-Disposition and also I don't really understand why I have to pass the formData variable to body and Content-Disposition header but this seems to work:
const formData = new FormData()
formData.append('avatar', avatar)
formData.append('model', model)
formData.append('id', id)
$fetch('/avatar', {
method: 'POST',
body: formData,
headers: { 'Content-Disposition': formData }
})
Still a bug in nuxt 3
I think the problem comes from the content-length header. The error happens before sending the request:
cause: RequestContentLengthMismatchError: Request body length does not match content-length header
at AsyncWriter.write (node:internal/deps/undici/undici:10139:19)
at writeIterable (node:internal/deps/undici/undici:10103:23) {
code: 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH'
Axios seems to be able to send the same exact request
@posva We're seeing people encounter issues with undici - do you encounter the same issue if you downgrade y our node version?
I get the same result with both node 18 and node 16 (latest patchs)
I did not know about
Content-Dispositionand also I don't really understand why I have to pass theformDatavariable tobodyandContent-Dispositionheader but this seems to work:const formData = new FormData() formData.append('avatar', avatar) formData.append('model', model) formData.append('id', id) $fetch('/avatar', { method: 'POST', body: formData, headers: { 'Content-Disposition': formData } })
when I set Content-Disposition to an arbitrary string, it works too
const formData = new FormData();
const keys = Object.keys(payload);
keys.forEach(key => {
formData.append(key, payload[key]);
});
$fetch(`/data-imports/`,
{
method: 'POST',
body: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
}
)
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
});
Can't send FormData. Any updates? By the way, I am using it in the Nuxt-2-bridge as the default package.
const formData = new FormData(); const keys = Object.keys(payload); keys.forEach(key => { formData.append(key, payload[key]); }); $fetch(`/data-imports/`, { method: 'POST', body: formData, headers: { 'Content-Type': 'multipart/form-data' } } ) .then(res => { console.log(res); }) .catch(error => { console.log(error); });Can't send FormData. Any updates? By the way, I am using it in the Nuxt-2-bridge as the default package.
The issue has been resolved after removing the Content-type from the request header and the browser will detect that automatically. And also check in the request header if the Accept: */* is like that or not.
As mentioned by @TusharRoy23, when using formData, do not specify a 'Content-Type' header, as it will automatically be set by fetch. @posva do you have a repro for this error 🙏🏽 ?
I don't have one anymore but should be reproducible (if still there) when trying to send images, something like https://vueuse.org/core/useFileDialog/#usefiledialog.
@Hebilicious I don't have. But If you still having this issue then you have to forcefully remove the Content-type from the header.
any solution to this, having same issue ,
EDIT: my server had issue , its working fine
I am having this issue. I am not setting the content type, but I am setting auth headers.
It keeps sending the content-type as application/json
Meanwhile, Axios works great with this setup without any magic. Just create its instance in nuxt plugin
Any update on this? Have to use vanilla fetch to have it working
same problem :/
same problem
I can confirm from the latest version:
- do not manually set
content-typeheader, it will be detected and set (with extra things like boundary) - no need to set
content-dispositionmanually
Excellent. If anyone is still experiencing this, please let me know and I'll happily reopen.
Hi, using nuxt 3, this doesn't work for me:
const formData = new FormData();
Object.keys(fields).forEach((field) => {
formData.append(field, fields[field]);
});
formData.append('file', new Blob([JSON.stringify(content)], { type: 'application/json' }));
//Investigate in the future why $fetch doesn't work!!!
const response = await $fetch(url, {
method: 'POST',
body: formData
});
console.log('Response: ',response);
It also doesn't work if I don't specify { type: 'application/json' } for the file.
Any ideas what I should do? My workaround at the moment is to use fetch instead of $fetch.
@belfortf assuming you mean that the form body is not being sent, both JSON and form bodies work fine for me. The content information headers should be set automatically too. Could you provide some code of how you handle the incoming request? Or if the error is something else maybe provide the error?
I have created ofetch instance to use inside the app. Every API call receives JSON data, but I have one endpoint that needs to send a formData instance. So, I need to manually disable the Content-Type header by setting it to undefined. Everything works, but I receive a typescript error. Maybe we need to extend our type definitions?
I have encountered a difference in the content type used by $fetch in Nuxt 3 (^3.12.4) compared to the native fetch and ofetch methods.
Specifically, $fetch utilizes application/json with Form Data, while the native fetch and ofetch methods use multipart/form-data; boundary=----WebKitFormBoundarySOMETHING. I'm curious to understand the reason behind this difference.
@gokhantaskan $fetch is created with ofetch and should not differ (except perhaps in internal requests, which are powered by unenv) so I would be grateful of a reproduction and new issue if you are happy to make one.
@gokhantaskan $fetch is created with ofetch and should not differ (except perhaps in internal requests, which are powered by unenv) so I would be grateful of a reproduction and new issue if you are happy to make one.
I noticed an issue with the $api implementation at the following URL, https://nuxt.com/docs/guide/recipes/custom-usefetch#custom-fetch. It seems that $fetch.create might be causing the problem. I don't have time to reproduce it right now, but I will attempt to do so tomorrow.
Tested with ofetchand $fetchdirectly in my Nuxt codebase, it automatically added the Content-Type header.
I've identified the issue, and it's on my end:
const $api = $fetch.create({
baseURL: config.public.apiPath,
credentials: "include",
// Convert request body to snake_case
onRequest({ options }) {
if (options.body) {
options.body = changeObjectKeysCase(options.body, "snake");
^^^ This line manipulates FormData and makes it plain object
}
},
...
I solved it with the following code:
onRequest({ options }) {
if (options.body) {
if (options.body instanceof FormData) {
const formData = new FormData();
for (const [key, value] of options.body.entries()) {
formData.append(snakeCase(key), value);
}
options.body = formData;
} else {
options.body = changeObjectKeysCase(options.body, "snake");
}
}
},