Axios Interceptor

Barisberkemalkoc
9 min readAug 6, 2023

--

Intelligent API requests

In this article, we will discuss how you can make your API requests faster and more convenient with Axios Interceptor.

Where is the interceptor ?

Web applications predominantly rely on APIs for data exchange, and in this realm, Axios emerges as an uncomplicated yet powerful HTTP client library. Nevertheless, grappling with prevalent challenges like session management, error handling, and security concerns during API requests can be formidable. This is precisely where the prowess of Axios interceptors becomes evident. In this article, we embark on an insightful journey to decipher the essence of Axios interceptors — uncovering their nature, mastering their usage, and appreciating their utility.

Axios is a promise-based HTTP Client for node.js and the browser. It is isomorphic (= it can run in the browser and nodejs with the same codebase). On the server-side it uses the native node.js http module, while on the client (browser) it uses XMLHttpRequests.

Axios Features

  • Make XMLHttpRequests from the browser
  • Make http requests from node.js
  • Supports the Promise API
  • Intercept request and response
  • Transform request and response data
  • Cancel requests
  • Timeouts
  • Query parameters serialization with support for nested entries
  • Automatic request body serialization to:
  • JSON (application/json)
  • Multipart / FormData (multipart/form-data)
  • URL encoded form (application/x-www-form-urlencoded)
  • Posting HTML forms as JSON
  • Automatic JSON data handling in response
  • Progress capturing for browsers and node.js with extra info (speed rate, remaining time)
  • Setting bandwidth limits for node.js
  • Compatible with spec-compliant FormData and Blob (including node.js)
  • Client side support for protecting against XSRF

Installing Axios

Before we dive into the world of Axios interceptors, it’s essential to have Axios installed in your project. If you haven’t added Axios to your project yet, worry not — the process is straightforward.

Using npm:

npm install axios

or using yarn :

yarn add axios

Remember, Axios provides a seamless way to interact with APIs, making the integration of interceptors even more potent. With Axios securely in place, we’re now ready to explore the world of interceptors and enhance the capabilities of our API requests.

What is the Axios ?

Making API Requests with Axios

Axios excels at simplifying the process of making API requests. With just a few lines of code, you can initiate HTTP GET, POST, PUT, or DELETE requests. Let’s take a look at a basic example:

Getting Data With Get Request

import axios from 'axios';

// Making a GET request
axios.get('https://api.bbm.com/posts')
.then(response => {
// Handle the successful response
console.log(response.data);
})
.catch(error => {
// Handle errors
console.error('An error occurred:', error);
});

In this example, we import Axios and use the axios.get method to retrieve data from the specified URL. The then block handles the successful response, while the catch block deals with any errors that might occur during the request.

// Making a GET request with query parameters
axios.get('https://api.bbm.com/posts', {
params: {
category: 'Oppenheimer',
limit: 42
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});

Often, you’ll need to include query parameters in your API requests.Here, the params object is used to attach query parameters to the URL, enhancing the precision of your API requests.

Sending Data with POST Requests

When sending data, especially for creating or updating resources, you’ll use HTTP POST or PUT requests.

// Making a POST request with data
const newData = {
title: 'Oohs Nolan!',
content: 'Oppenheimer was one of the best cinematographic films
I have ever seen.'
};

axios.post('https://api.bbm.com/posts', newData)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});

In this case, Axios’s axios.post method is employed to send the newData object to the server, creating a new post.

Configuring Request Headers

// Making a GET request with custom headers
const config = {
headers: {
Authorization: 'Bearer ACCESS_TOKEN'
}
};

axios.get('https://api.example.com/protected-resource', config)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});

Request headers are essential for various purposes, such as authorization or content negotiation.By setting the headers property in the config object, you can include custom headers in your requests.

Concurrent Requests

const requestForPosts = axios.get('https://api.bbm.com/posts');
const requestForTitles = axios.get('https://api.bbm.com/titles');

axios.all([requestForposts, requestForTitles])
.then(axios.spread((responseForPosts, responseForTitles) => {
console.log('Response from request for posts:', responseForPosts.data);
console.log('Response from request for titles:', responseForTitles.data);
}))
.catch(error => {
console.error(error);
});

Axios enables you to perform multiple requests concurrently and handle their results using axios.all

How can we make the Axios methods I’ve shown more useful?

Imagine having a personal assistant who anticipates your needs, streamlines your tasks, and enhances your interactions — that’s precisely what Axios Interceptors bring to the world of web development. These unsung heroes are the secret ingredients that transform Axios from an ordinary HTTP client into an extraordinary tool. Interceptors empower you to intercept and influence requests and responses as they traverse between your application and the server. This magical ability opens doors to a profusion of advantages:

From injecting authentication tokens seamlessly into every request, to handling errors with elegance and poise. Say goodbye to repetitive code, tangled error-handling mechanisms, and manual token injections — with interceptors, your application becomes smarter, cleaner, and remarkably efficient. In this journey, we’ll unravel the captivating world of Axios interceptors, discovering how they streamline workflows, fortify security, and elevate your development experience to a whole new level.

Understanding Axios Interceptors:

Axios interceptors are middleware functions that allow you to tap into the request and response flows. They offer a gateway to modify, authenticate, or handle errors at a centralized level.

Setting Up a Global Request Interceptor:

Imagine needing to include an authentication token in every request’s headers.Here is the solution to this hysteria with interceptor.

axios.interceptors.request.use(config => {
const authToken = localStorage.getItem('authToken');
if (authToken) {
config.headers.Authorization = `Bearer ${authToken}`;
}
return config;
});

Streamlining Error Handling:

Interceptors are also adept at consolidating error handling. Say goodbye to scattered .catch blocks. Here's an example of catching and handling errors elegantly.

axios.interceptors.response.use(
response => response,
error => {
const status = error.response ? error.response.status : null;

if (status === 401) {
// Handle unauthorized access
} else if (status === 404) {
// Handle not found errors
} else {
// Handle other errors
}

return Promise.reject(error);
}
);

Optimizing Requests:

Interceptors enable data transformation before it reaches your application. This is particularly useful when data needs to be normalized or parsed. Imagine receiving an array of objects, but your app requires a specific format:

axios.interceptors.response.use(response => {
response.data = response.data.map(item => ({
id: item.id,
name: item.title
}));
return response;
});

Refreshing Authentication Tokens:

In the context of authentication, interceptors can automatically refresh expired tokens. No more manually handling token refreshes:

axios.interceptors.response.use(
response => response,
async error => {
if (error.response.status === 401) {
const newToken = await refreshToken();
localStorage.setItem('authToken', newToken);
// Retry the original request
return axios(error.config);
}
return Promise.reject(error);
}
);

Use Cases For You (With Samples)

Scenario: Your e-commerce application requires an authentication token to be included in the headers of every API request for secure access to user data.

Explanation: User authentication is paramount in an e-commerce application to ensure that only authorized users can access sensitive data. Instead of manually adding the authentication token to each request, an Axios Interceptor can automate this process.

Imagine a scenario where a user is viewing their order history. To fetch this data, your application makes an API request as follows:

axios.get('https://api.bbm.com/orders')
.then(response => {
// Handle successful response
console.log(response.data);
})
.catch(error => {
// Handle errors
console.error(error);
});

Now, let’s add an interceptor to inject the authentication token:

axios.interceptors.request.use(config => {
const authToken = localStorage.getItem('authToken');
if (authToken) {
config.headers.Authorization = `Bearer ${authToken}`;
}
return config;
});

With the interceptor in place, the same request will now automatically include the user’s authentication token.

Scenario: Your social media application interacts with multiple APIs, each returning different error structures. Consistently handling these errors is a challenge.

Explanation: In a social media application, API responses can include various error formats such as 404 errors for missing posts or 403 errors for unauthorized access. Instead of writing specific error-handling logic for each API call, you can use an interceptor to centralize error handling.

Suppose a user is trying to like a post:

axios.post('https://api.bbm.com/posts/oppenheimer57ac38957/like')
.then(response => {
// Handle successful like
console.log(response.data);
})
.catch(error => {
// Handle errors
console.error(error);
});

Now, let’s implement an interceptor to handle errors consistently:

axios.interceptors.response.use(
response => response,
error => {
const status = error.response ? error.response.status : null;

if (status === 401) {
// Handle unauthorized access
console.log("Unauthorized access");
} else if (status === 404) {
// Handle not found errors
console.log("Post not found");
} else {
// Handle other errors
console.error("An error occurred:", error);
}

return Promise.reject(error);
}
);

With the interceptor, error handling is streamlined.

Cancelling Interceptors

Axios Interceptors can be powerful tools for managing API requests and responses, but there are scenarios where you might want to cancel or ignore certain interceptors for specific requests. Cancelling interceptors can be beneficial when you want to avoid unwanted side effects, such as applying global interceptors to requests where they’re not appropriate or necessary. There are several situations where cancelling interceptors might be necessary.

Avoiding Duplicate Actions: If you have multiple interceptors that modify requests in a similar way (e.g., adding headers), you might want to cancel one of them to avoid duplication.

Preventing Interference: Some requests might require a distinct set of interceptors due to their unique requirements. Cancelling certain interceptors can prevent interference with the intended behavior of these requests.

Optimizing Performance: In cases where you have complex or resource-intensive interceptors, cancelling them for specific requests can help optimize performance and reduce unnecessary overhead.

To cancel an interceptor in Axios, you need to store the reference to the interceptor during its creation and then use the eject method to remove it.

// Creating an interceptor and storing its reference
const axiosInterceptor = axios.interceptors.request.use(config => {
// Modify the request config
return config;
});

// Removing the interceptor
axios.interceptors.request.eject(axiosInterceptor);

In the example above, myInterceptor is the reference to the interceptor. By calling axios.interceptors.request.eject(axiosInterceptor), you're removing that specific interceptor. This way, the interceptor will no longer affect subsequent requests.

Scenario: You have a global request interceptor that adds an authorization token to the headers of every request. However, for a specific request, you want to exclude this token.

// Creating a global request interceptor
const authInterceptor = axios.interceptors.request.use(config => {
const authToken = localStorage.getItem('authToken');
if (authToken) {
config.headers.Authorization = `Bearer ${authToken}`;
}
return config;
});

// Making a request without the global interceptor
axios.get('https://api.bbm.com/get-oppenheimer-data')
.then(response => {
// Handle the response
console.log(response.data);
})
.catch(error => {
// Handle errors
console.error(error);
})
.finally(() => {
// Eject the interceptor to prevent it from affecting other requests
axios.interceptors.request.eject(authInterceptor);
});

Config For Axios Interceptor (With Sample)

1.Sending Data in Request Payload:

axios.interceptors.request.use(config => {
config.data = {
title: 'New Post',
content: 'This is the content of the new post.'
};
return config;
});

axios.post('https://api.bbm.com/posts')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});

2. Handling Query Parameters:

axios.interceptors.request.use(config => {
config.params = {
category: 'oppenheimer',
limit: 42
};
return config;
});

axios.get('https://api.bbm.com/posts')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});

3. Uploading Files using FormData with an Interceptor:

axios.interceptors.request.use(config => {
if (config.data instanceof FormData) {
config.headers['Content-Type'] = 'multipart/form-data';
}
return config;
});

const formData = new FormData();
formData.append('oppenheimer-file', fileInput.files[0]);

axios.post('https://api.bbm.com/upload', formData)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});

4. Handling Timeouts with an Interceptor:

axios.interceptors.request.use(config => {
config.timeout = 4200; // Set a timeout of 4.2 seconds
return config;
});

axios.get('https://api.bbm.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
if (error.code === 'ECONNABORTED') {
console.error('Request timed out');
} else {
console.error(error);
}
});

5. Canceling Requests with Axios Cancel Tokens and Interceptor:

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.interceptors.request.use(config => {
config.cancelToken = source.token;
return config;
});

axios.get('https://api.bbm.com/data')
.then(response => {
console.log(response.data);
})
.catch(thrown => {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
console.error(thrown);
}
});

// Cancel the request
source.cancel('Request canceled by the user.');

In the realm of web development, where efficient data exchange is paramount, Axios emerges as a formidable ally. In this journey through the world of Axios interceptors, we’ve uncovered a treasure trove of capabilities that can revolutionize the way we handle API requests and responses. From seamlessly injecting authentication tokens to streamlining error handling and optimizing data transformations, interceptors offer a toolkit that empowers developers to craft more elegant, secure, and performant applications. As you venture forward, remember that interceptors are not just about functionality; they’re about achieving cleaner code, consistent behaviors, and a more pleasant development experience. With Axios interceptors, you’re not just making API calls; you’re shaping the future of your applications with every well-timed intercept. So go forth, embrace these interceptors, and elevate your web development journey to new heights.

Thanks for reading — BBM

--

--