I want to set _boundry
in my header.
First, I dispatch the form data:
//ponent.js
const form = new FormData();
form.append('email', '[email protected]')
form.append('password', '12121212')
dispatch(FetchLogin.action(form))
Second, I prepare api call;
//loginService.js
import api from '@/Services'
export default async form => {
const response = await api.post('user/login/', form)
return response.data
}
Third, I make api call;
//Services/index.js
import axios from 'axios'
import { Config } from '@/Config'
const instance = axios.create({
baseURL: Config.API_URL,
headers: {
'Content-Type': `multipart/form-data; boundary=${form._boundary}`, //Cannot access form here
},
timeout: 3000,
})
instance.interceptors.response.use(
response => response,
({ message, response: { data, status } }) => {
return handleError({ message, data, status })
},
)
export default instance
I want to access form
data within to axios
instance
to be able to use form._boundry
in headers
.
How can I pass form
data from loginService.js
to Services/index.js
?
I want to set _boundry
in my header.
First, I dispatch the form data:
//ponent.js
const form = new FormData();
form.append('email', '[email protected]')
form.append('password', '12121212')
dispatch(FetchLogin.action(form))
Second, I prepare api call;
//loginService.js
import api from '@/Services'
export default async form => {
const response = await api.post('user/login/', form)
return response.data
}
Third, I make api call;
//Services/index.js
import axios from 'axios'
import { Config } from '@/Config'
const instance = axios.create({
baseURL: Config.API_URL,
headers: {
'Content-Type': `multipart/form-data; boundary=${form._boundary}`, //Cannot access form here
},
timeout: 3000,
})
instance.interceptors.response.use(
response => response,
({ message, response: { data, status } }) => {
return handleError({ message, data, status })
},
)
export default instance
I want to access form
data within to axios
instance
to be able to use form._boundry
in headers
.
How can I pass form
data from loginService.js
to Services/index.js
?
1 Answer
Reset to default 9When performing AJAX requests from a browser (via fetch
or XMLHttpRequest
), the runtime knows what to do for certain request body formats and will automatically set the appropriate Content-type
header
If the request body is a
FormData
instance, theContent-type
will be set tomultipart/form-data
and will also include the appropriate mime boundary tokens from the data instance.All of these examples will post the data as
multipart/form-data
with appropriate mime boundary tokensconst body = new FormData(); // attach files and other fields body.append("file", fileInput.files[0]); body.append("foo", "foo"); body.append("bar", "bar"); // fetch fetch(url, { method: "POST", body }); // XMLHttpRequest const xhr = new XMLHttpRequest(); xhr.open("POST", url); xhr.send(body); // Axios axios.post(url, body);
If the request body is a
URLSearchParams
instance, theContent-type
will be set toapplication/x-www-form-urlencoded
All of these examples will post the data as
application/x-www-form-urlencoded
const body = new URLSearchParams({ foo: "foo", bar: "bar" }); // serialises to "foo=foo&bar=bar" // fetch fetch(url, { method: "POST", body }); // XMLHttpRequest const xhr = new XMLHttpRequest(); xhr.open("POST", url); xhr.send(body); // Axios axios.post(url, body);
You only need to manually set the content-type
if you intend to send string data in a particular format, eg text/xml
, application/json
, etc since the runtime cannot infer the type from the data.
const body = JSON.stringify({ foo: "foo", bar: "bar" });
// fetch
fetch(url, {
method: "POST",
headers: {
"content-type": "application/json",
},
body
});
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader("content-type", "application/json");
xhr.send(body);
On Axios
Axios will automatically stringify JavaScript data structures passed into the data
parameter and set the Content-type
header to application/json
so you only need minimal configuration when dealing with JSON APIs
// no extra headers, no JSON.stringify()
axios.post(url, { foo: "foo", bar: "bar" })
Under the hood, Axios uses XMLHttpRequest
so the specifications for FormData
and URLSearchParams
also apply.
Axios v0.27.1 is broken
This specific version of Axios is unable to make a proper request with FormData
. Do not use it!
Axios v1.0.0+ is broken
This is verging into my own opinion but every Axios release post v1.0.0 has been fundamentally broken in one way or another. I simply cannot remend anyone use it for any reason.
Much better alternatives are:
- The Fetch API (also available in Node v18+)
- got for Node.js
- ky for browsers
NodeJS
When using Axios from the backend, it will not infer Content-type
headers from FormData
instances. You can work around this using a request interceptor.
axios.interceptors.request.use(config => {
if (config.data instanceof FormData) {
Object.assign(config.headers, config.data.getHeaders());
}
return config;
}, null, { synchronous: true });
or simply merge in the headers when making a request
axios.post(url, body, {
headers: {
"X-Any-Other-Headers": "value",
...body.getHeaders(),
},
});
See https://github./axios/axios#form-data
On jQuery $.ajax()
jQuery's $.ajax()
method (and convenience methods like $.post()
) default to sending request body payloads as application/x-www-form-urlencoded
. JavaScript data structures will be automatically serialised using jQuery.param() unless told not to. If you want the browser to automatically set the Content-type
header based on the body format, you also need to configure that in the options
const body = new FormData()
body.append("foo", "foo")
body.append("bar", "bar")
$.ajax({
url,
method: "POST",
data: body,
contentType: false, // let the browser figure it out
processData: false // don't attempt to serialise data
})