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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs