12

Setting up Axios Interceptors for all HTTP calls in an application

 3 years ago
source link: https://blog.bitsrc.io/setting-up-axios-interceptors-for-all-http-calls-in-an-application-71bc2c636e4e
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Setting up Axios Interceptors for all HTTP calls in an application

Automatically intercept all the requests and responses so you don’t have to remember to do it yourself.

Image for post
Image for post
Photo by Lars Kienle on Unsplash

As the Internet gets more mature and sophisticated, gathering the data to do those complex things gets more complicated too.

Think about it: at the advent of the Internet you could send and receive email, search by keywords for information and visit a few, extremely basic websites. Today, you can: order a car and have it pick you up at your exact location within minutes, make purchases with a credit card number stored on your phone, search for extremely specific questions via voice and get thousands of useful, relevant answers. It’s amazing what’s at our fingertips now with very little effort on our part.

And as the Internet has grown more useful to us as users, it’s also grown more complex for us as developers to get the all the data needed to be so helpful, which is where my story today begins.

As a software engineer, the vast majority of the data I work with lives somewhere besides my application and the databases my team is responsible for. So I spend a lot of time requesting data, receiving data, validating data, reshaping data — all via HTTP calls to applications beyond my own.

A lot of the time, those HTTP calls aren’t so simple either: I can’t just send a GET or a POST and expect a 200 response. These HTTP calls need cookies, authorization tokens, secured headers, JWTs, API keys or other methods of verification — the teams I’m requesting that data from need to know my application is allowed to interact with the information they’re responsible for.

And that’s totally valid and very normal nowadays; systems need to prove they’re allowed to see or change data. It can’t just available for anyone with an Internet connection who knows the URL to their service, that could be very dangerous.

But although this is normal, ensuring every single, solitary HTTP request or response has all the info it needs to pass muster can be extremely repetitive to set up (and easy to forget to add). But it doesn’t have to be. With the help of the popular JavaScript HTTP client Axios, you can set up interceptor functions to catch every HTTP request or response and do whatever needs to happen without you even having to think about it — which is the best solution.

Write the code once, and don’t worry about it again. Ready to improve your coding life?

Tip: Share your reusable components between projects using Bit (Github).

Bit makes it simple to share, document, and reuse independent components between projects. Use it to maximize code reuse, keep a consistent design, collaborate as a team, speed delivery, and build apps that scale.

Bit supports Node, TypeScript, React, Vue, Angular, and more.

Image for post
Image for post
Exploring shared components on Bit.dev

Meet Axios

In case you’re not familiar with it, Axios is an extremely popular promise based HTTP client for JavaScript in the browser and Node.js on the server.

In addition to all the basic CRUD (create, read, update, delete) functionality you’d expect from any HTTP client, out of the box Axios offers a lot of other helpful features like: configuration defaults, error handling, request canceling, automatically serializing JavaScript objects to JSON and more, but the feature I want to focus on today is Axios’ interceptors.

Axios Interceptors

Interceptors are a feature that allows an application to intercept requests or responses before they are handled by the .then() or the .catch().

Why is this helpful, you ask? Well, as I mentioned above, suppose every HTTP request needs a header property attached to it, in order to verify the application requesting data is allowed to access that data. Or suppose, that sometimes the HTTP response that comes back is a bad response — a 400 or 500 status. At those times, you might want to automatically retry the request or verify the authorization that was rejected is actually still valid.

Axios makes setting up interceptors really easy, and from my own personal experience it doesn’t seem to matter much where in a project’s files they’re located, they just seem to work. Let’s go through some examples of each sort of interceptor.

Intercepting Requests

The first code example I will show is how to set up an Axios request interceptor. The example is written inside of a React application, but I expect the process to be similar regardless of which JavaScript framework (or not) you’re using.

Both types of Axios interceptors accept two functions. The first function of the request interceptor modifies the request if it’s a valid, successful request, the second function handles when the request is invalid and throws an error.

This particular code lives at the root of the React application in its index.js file inside the src/ folder.

index.js

Image for post
Image for post
Axios request interceptor example attaching a header with the user’s username if particular URLs are about to be requested.

In the example above, axios is imported at the top of the file with ES6 import syntax, then it’s ready to be used. I’m using ES6 arrow functions in my example, but it translates to basic JavaScript as:

axios.interceptors.request.use(
function(successfulReq) {
...modify code; return successfulReq;
},
function(error) {
...return Promise.reject(error);
}
);

Then do whatever needs doing to the request before the outgoing HTTP request is sent from the server side of the application.

The purpose of this particular interceptor is: whenever the application makes an HTTP request to one of the supporting services whose URLs include checkout, billing, or order, Axios automatically attaches a header to the request with the username stored in state. In my case, Redux is holding the user’s information in state, but it could be stored in local storage, in session storage — wherever it makes sense.

If the HTTP request is not about to go to one of those services, the interceptor does nothing to modify the request and lets it go on its way unaltered.

And if the request is somehow malformed, the second function, the error() function will kick in and throw an error rejecting the request and giving a reason why.

Not too complicated, right? Intercepting responses can be just as simple.

Intercepting Responses

I have two examples of response interceptors I want to show you, because both are informative and both of these occur in different parts of the application: one on the client side in the browser (like the request interceptor example) and the other on the server side — the Node.js side.

Just like request interceptors, response interceptors accept two function arguments: the first function is when the response that comes back is a 200 status HTTP response, the second function is when it’s a status code that falls outside of the 200 range. It’ll make more sense when I go through the examples below.

Client Side Example

The first example lives close to the root of my React application once again, however, it is not in the same file as the request interceptor, it is in the App.js file within the src/ folder.

App.js

Image for post
Image for post
An example of a request interceptor in the React portion of the application that exists to check if a user’s browser credentials are still valid if it receives a 401 unauthorized HTTP response.

Since this is in the React-portion of the application, the Axios library is imported at the top of the file: import axios from 'axios';, and then the request interceptor is invoked with

axios.interceptors.response.use(
function(successRes) {
... modify response;
return successRes;
},
function(error) {
... return Promise.reject(error);
}
);

My particular example is only if an HTTP response comes back from a service with a 401 unauthorized error, hence the reason the first argument passed to the response interceptor is undefined. If the response is any sort of 200 response, the Axios interceptor doesn’t worry about it.

If the HTTP response is 401, however, my second function (the axiosRetryInterceptor() function) fires up, and checks if the logged in user’s credentials are still valid — because a 401 indicates perhaps the user’s authorization token, cookie or session has expired. If the user’s session has indeed expired, then the isUserValid() function will end up logging the user out of the app and requiring them to sign in again, if not, isUserValid() will return that is not the reason for the 401 and the user can continue with their session.

So that’s one example of an Axios response interceptor on the client side, now let’s look at one on the server side.

Server Side Example

The second response interceptor happens on the server side of my application and uses the CommonJS style of imports:

const axios = require('axios');

Once it’s instantiated using the require-syntax, the usage of the actual interceptor is almost identical to the one in the browser. Here’s a response interceptor that lives near the the root of the Node.js server inside the server/ folder.

server.js

Image for post
Image for post
A server side example of an Axios response interceptor that logs positive responses, and retries failed responses.

This particular response interceptor has two functions. The first anonymous function logs which method was called (GET, POST, etc.), which microservice was called (checkout, orders, etc.) and which successful response status was issued (200, 204, etc.).

The second function, axiosRetryInterceptor(), is invoked when an HTTP status besides 200 is received. If a 400 or 500 status is received, this function will retry the original request in hopes of getting some sort of 200 response. It will retry up to 3 times, and each time it will lengthen the amount of time between requests to the service that’s responding with an error.

It’s a little convoluted because of the backoff variable that delays the next attempt to call the server, but that’s essentially all this response interceptor is actually doing.

And there you have it, Axios request and response interceptors in a nutshell. Not too bad to implement and pretty handy, don’t you think?

Conclusion

The Internet today is complicated, and only getting more so. But luckily for us web developers, there’s some nifty JavaScript packages out there to handle some of the complexity for us.

The complexity I’m focusing on today is the kind caused by lots of other services owning the data our applications need. Often our apps need to send some sort of proof that they are authorized to access the data those services have, or they need to know what to do if the other services reject their request, and that’s where Axios interceptors come in handy.

These little functions will automatically intercept every single outgoing HTTP request or incoming HTTP response, and if the request or response matches the parameters set by the interceptor, it will modify those payloads however the developers see fit. Need to send auth headers with every request? Done. Need to retry a request if the service sends back a 500 response? No problem. Axios interceptors were built precisely for these scenarios.

Check back in a few weeks — I’ll be writing more about JavaScript, React, ES6, or something else related to web development.

Thanks for reading. I hope you give these interceptors a try in your own code — why bother trying to remember to perfectly form all your payloads or responses yourself when you can let Axios give you a helping hand?

References & Further Resources


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK