Understanding Axios Request Interceptors

This article explains how request interceptors operate within the Axios HTTP client lifecycle. It covers the sequential execution model of interceptors, how they allow developers to inspect and mutate outgoing request configurations, how asynchronous operations and errors are processed before a request leaves the client, and how to manage interceptor lifecycles effectively.

The Interceptor Execution Pipeline

In standard Axios operations, calling a method like axios.get() or axios.post() initiates an HTTP request directly to the target server. Request interceptors act as middleware positioned between the initiation of the request call and the actual dispatch of the network request via XMLHttpRequest or Node.js HTTP adapters.

When a request is initiated, Axios constructs a promise chain. The request interceptor functions are placed at the beginning of this chain. The request configuration object (AxiosRequestConfig) is passed sequentially through each registered request interceptor before the network adapter receives it.

Application Code (axios.get) 
        ↓
Request Interceptors (Mutate config / Add headers)
        ↓
Network Adapter (Dispatches HTTP Request)
        ↓
Server

Registering a Request Interceptor

Request interceptors are registered using the axios.interceptors.request.use() method. This method accepts two callback functions:

  1. Fulfilled Handler: Receives the current config object, applies mutations or side effects, and must return the modified config (or a Promise resolving to it).
  2. Rejected Handler: Handles errors that occur during the configuration phase before the network request is initiated.
axios.interceptors.request.use(
  (config) => {
    // Modify config before request is sent
    config.headers.Authorization = `Bearer ${getAuthToken()}`;
    return config;
  },
  (error) => {
    // Handle request setup errors
    return Promise.reject(error);
  }
);

Key Capabilities and Behaviors

1. Configuration Mutation

The fulfilled handler has direct access to all request parameters, including headers, parameters, the base URL, payload data, and timeout settings. Any modifications made to the config object are carried forward to the network request.

2. Asynchronous Operations

Request interceptors support asynchronous logic natively. If the fulfilled handler returns a Promise, Axios pauses the execution chain until that Promise resolves. This is standard for refreshing expired authentication tokens or retrieving access credentials from asynchronous storage before allowing the request to proceed.

axios.interceptors.request.use(async (config) => {
  const token = await fetchSecureToken();
  config.headers['X-Access-Token'] = token;
  return config;
});

3. Execution Order

Axios executes multiple request interceptors in reverse order of their registration (last registered runs first). Each interceptor receives the config returned by the previous one.

4. Short-Circuiting and Error Handling

If an error is thrown within a request interceptor or if the rejected handler returns Promise.reject(), the execution skips the network adapter entirely and passes directly to the response error pipeline.

Removing Interceptors

To prevent memory leaks or unwanted transformations, interceptors can be removed dynamically using the eject method:

const myInterceptor = axios.interceptors.request.use((config) => config);
axios.interceptors.request.eject(myInterceptor);