JAVASCRIPT
Centralized Axios API Client with Interceptors
Build a reusable Axios instance with interceptors for global error handling, adding authorization headers, and request/response logging.
import axios from 'axios';
// Create a custom Axios instance
const apiClient = axios.create({
baseURL: 'https://api.example.com/v1',
timeout: 10000, // Request timeout in ms
headers: {
'Content-Type': 'application/json',
},
});
// Request Interceptor: Add authorization token
apiClient.interceptors.request.use(
config => {
const token = localStorage.getItem('authToken'); // Or from a state management store
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
// Optional: Log request details
// console.log('Request:', config.method?.toUpperCase(), config.url, config.data || config.params);
return config;
},
error => {
// Handle request errors (e.g., network issues before sending)
console.error('Request error:', error);
return Promise.reject(error);
}
);
// Response Interceptor: Handle global errors, refresh tokens, etc.
apiClient.interceptors.response.use(
response => {
// Optional: Log response data
// console.log('Response:', response.config.url, response.status, response.data);
return response;
},
async error => {
const originalRequest = error.config;
// Example: Handle 401 Unauthorized globally (e.g., for token refresh)
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
// Implement token refresh logic here
// try {
// const refreshToken = localStorage.getItem('refreshToken');
// const { data } = await axios.post('/auth/refresh-token', { refreshToken });
// localStorage.setItem('authToken', data.newToken);
// apiClient.defaults.headers.common['Authorization'] = `Bearer ${data.newToken}`;
// return apiClient(originalRequest); // Retry the original request with new token
// } catch (refreshError) {
// console.error('Token refresh failed:', refreshError);
// // Redirect to login or clear auth data
// // window.location.href = '/login';
// return Promise.reject(refreshError);
// }
console.warn('401 Unauthorized - token refresh logic would go here.');
}
// Handle other errors
console.error('Response error:', error.response?.status, error.response?.data || error.message);
return Promise.reject(error);
}
);
export default apiClient;
// Example Usage (in another file):
// import apiClient from './apiClient';
//
// async function getUserData() {
// try {
// const response = await apiClient.get('/users/me');
// console.log('User data:', response.data);
// } catch (error) {
// console.error('Failed to get user data:', error);
// }
// }
//
// async function createPost(postData) {
// try {
// const response = await apiClient.post('/posts', postData);
// console.log('Post created:', response.data);
// } catch (error) {
// console.error('Failed to create post:', error);
// }
// }
How it works: This snippet demonstrates creating a centralized API client using Axios, a popular promise-based HTTP client for JavaScript. It leverages Axios's powerful interceptor system to inject common functionalities like adding authorization tokens to every outgoing request, globally handling network or API errors (e.g., 401 Unauthorized for token refresh), and performing request/response logging. This approach promotes a DRY (Don't Repeat Yourself) principle, making API interactions cleaner, more consistent, and easier to manage across your entire application.