Reputation: 1741
This is my axios configuration:
import axios from "axios"
const axiosApi = axios.create({
baseURL: import.meta.env.VITE_API_URL
})
const requestInterceptor = config => {
config.headers['Content-Type'] = 'application/json';
config.headers['Accept'] = 'application/json';
config.headers['X-Client'] = 'React';
return config;
}
axiosApi.interceptors.request.use(requestInterceptor);
const get = async (url) => {
return await
axiosApi.get(url, {
crossDomain: true
}).then(response => {
return response?.data;
})
}
const post = async (url, data) => {
return await axiosApi
.post(url, Array.isArray(data) ? [...data] : { ...data })
.then(response => response?.data)
}
const form = async (url, data) => {
return await axiosApi
.post(url, data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(response => response?.data)
}
As you can see, for post
and get
utility methods I use a request interceptor that sets the default values. Thus I use Content-Type: application/json
for them.
However, for form
I overrode the Content-Type
header to be a form.
I read some other questions, including:
Axios not passing Content-Type header
Axios Header's Content-Type not set for safari
But my server allows Content-Type
to be sent in CORS requests:
Access-Control-Allow-Headers: authorization,content-type,x-client
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: *
But when I use form
method, I see that the Content-Type
is not set to application/json
, not application/x-www-form-urlencoded
.
What have I done wrong?
Upvotes: 8
Views: 14779
Reputation: 164736
By default Axios has excellent request body handling.
application/json
.URLSearchParams
, it uses application/x-www-form-urlencoded
.FormData
instance and it will use multipart/form-data
So why are there endless questions on Stack Overflow with customised content-type
headers? I'd even go so far as to argue that unless your APIs are using proper content negotiation, you don't need to mess with the Accept
header either.
I see no need for an interceptor in your case. Simply set the request header defaults on your instance
axiosApi.defaults.headers.common["X-Client"] = "React";
// and if your API actually uses content negotiation...
// axiosApi.defaults.headers.common.Accept = "application/json";
As for your url-encoded request, Axios 0.x supports this via URLSearchParams
or a plain string. It will not automatically convert a plain object into application/x-www-form-urlencoded
.
If your data
is a flat object, you can use the following
const form = async (url, data) => {
const encodedData = new URLSearchParams(data);
return (await axiosApi.post(url, encodedData)).data;
};
If it's more complex, I would recommend using a library like qs.
Otherwise, wait for Axios 1.0 where you can apparently use this
axios.post(url, data, {
headers: { "content-type": "application/x-www-form-urlencoded" }
});
Upvotes: 8