'Pass Data to Service in Axios
I want to set _boundry in my header.
First, I dispatch the form data:
//component.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?
Solution 1:[1]
This question seems to come up often enough yet I cannot seem to find a canonical answer so here goes...
When 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
FormDatainstance, theContent-typewill be set tomultipart/form-dataand will also include the appropriate mime boundary tokens from the data instance.All of these examples will post the data as
multipart/form-datawith appropriate mime boundary tokensconst body = new FormData(); 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
URLSearchParamsinstance, theContent-typewill be set toapplication/x-www-form-urlencodedAll of these examples will post the data as
application/x-www-form-urlencodedconst 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 provides defaults of Accept: application/json and Content-type: application/json for POST, PUT and PATCH requests. It will also automatically stringify JavaScript data structures passed into the data parameter 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 0.27.1 is broken
This specific version of Axios is unable to make a proper request with FormData. Do not use it!
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 });
See https://github.com/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
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
