Axios
lastmod 2025-12-29created 2019-01-1426 edits
Promise based HTTP client for the browser and node.js
Categories
- Jest:Mock:Axios - How to test an axios mockup in jest.
- axios-mock-adapter - A library that issues fake requests when using axios
Interceptors
- Managing APIs with axios interceptors
- Interceptors | Axios Learning Guide
- Axios: Handle Error Response with 200 Status Code
client.interceptors.response.use(res => {
if (res.data.status === false) {
// Error message is retrived from the JSON body.
const error = new Error(res.data.message);
// Attach the response instance, in case we would like to access it.
error.response = res;
throw error;
}
// If the status is true, simply return back the response instance.
return res;
});
How to turn a Status Code into an error
Using the validateStatus config option, you can define HTTP code(s) that should throw an error.
axios.get('/user/12345', {
validateStatus: function (status) {
return status < 500; // Resolve only if the status code is less than 500
}
})
Await request
async function getUser() {
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
}
}
Simple example
Performing a POST request:
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
Performing multiple concurrent requests:
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
Promise.all([getUserAccount(), getUserPermissions()])
.then(function (results) {
const acct = results[0];
const perm = results[1];
});
When you want to skip Interceptors
axios.interceptors.response.use(undefined, err => {
if (err.status === 401 && err.config && !err.config.__isRetryRequest) {
refreshLogin(getRefreshToken(),
success => {
setTokens(success.access_token, success.refresh_token)
err.config.__isRetryRequest = true
err.config.headers.Authorization = 'Bearer ' + getAccessToken()
axios(err.config)
},
error => { console.log('Refresh login error: ', error) }
)
}
})
Personally, rather than adding a new Property to err.config, I prefer adding it to error.config.headers, since that doesn't break the type symbols. (Though there's no way to avoid sending that header to the server...)
Alternatively, use the same axios.create() to make a new instance. (In that case, when testing, you have to pass the instance to a mocking object like axios-mock-adapter for the tests to work properly,,, which isn't great either~;;;)
Form submission (application/x-www-form-urlencoded)
By default, axios serializes JavaScript objects to 'JSON'. To send data instead of in the application/x-www-form-urlencoded format, you can use one of the following options.
Browser
In a browser, you can use the URLSearchParams API as follows.
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
| NOTE |
| URLSearchParams is not supported by all browsers, but there is a polyfill (url-search-params) available. |
Alternatively, you can encode the data using the qs library.
If you are using ES6+, you can write it as follows.
import qs from 'qs';
const data = { 'bar': 123 };
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url,
};
axios(options);
Node.js
You can use the querystring module as follows.
const querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
Of course, you can also use the qs library.
| NOTE |
| The querystring method of Node.js has problems stringifying nested objects. If you often need to stringify nested objects, the qs library is recommended. |
Parameter Serializer
The qs module makes this easy.
import axios from 'axios';
import qs from 'qs';
axios.defaults.baseURL = process.env.REACT_APP_BASE_URL || window.location.origin;
axios.defaults.headers.post['Accept'] = 'application/json';
axios.defaults.paramsSerializer = params => {
return qs.stringify(params)
};
Renewing JWT Refresh tokens with Axios
- [Recommended] Refreshing tokens with axios interceptors 1
let isTokenRefreshing = false;
let refreshSubscribers = [];
const onTokenRefreshed = (accessToken) => {
refreshSubscribers.map((callback) => callback(accessToken));
};
const addRefreshSubscriber = (callback) => {
refreshSubscribers.push(callback);
};
axios.interceptors.response.use(
(response) => {
return response;
},
async (error) => {
const {
config,
response: { status },
} = error;
const originalRequest = config;
if (status === 401) {
if (!isTokenRefreshing) {
// isTokenRefreshing이 false인 경우에만 token refresh 요청
isTokenRefreshing = true;
const refreshToken = await AsyncStorage.getItem("refreshToken");
const { data } = await axios.post(
`http://localhost:3000/refresh/token`, // token refresh api
{
refreshToken,
}
);
// 새로운 토큰 저장
const {
accessToken: newAccessToken,
refreshToken: newRefreshToken,
} = data;
await AsyncStorage.multiSet([
["accessToken", newAccessToken],
["refreshToken", newRefreshToken],
]);
isTokenRefreshing = false;
axios.defaults.headers.common.Authorization = `Bearer ${newAccessToken}`;
// 새로운 토큰으로 지연되었던 요청 진행
onTokenRefreshed(newAccessToken);
}
// token이 재발급 되는 동안의 요청은 refreshSubscribers에 저장
const retryOriginalRequest = new Promise((resolve) => {
addRefreshSubscriber((accessToken) => {
originalRequest.headers.Authorization = "Bearer " + accessToken;
resolve(axios(originalRequest));
});
});
return retryOriginalRequest;
}
return Promise.reject(error);
}
);
See also
Favorite site
- Github - axios project site
- [Recommended] Axios Learning Guide
- Axios vs Fetch for beginners
- Compares the two APIs, both Promise-based HTTP Clients
- Explains from a syntax comparison to the differences when calling the JSONPlaceholder API
- Error handling/timeouts/cancellation
References
-
Maruzzings_devlog_-_axios_interceptors_token_refresh.pdf ↩