October 7, 2024 (3mo ago)
Axios Global Interceptor Config
Interceptor Config
create a new file with the name axios.ts
add the validation for api url from environmentConstants
import { apiBaseUrl } from "../constants/environmentConstants" ;
if ( ! apiBaseUrl) {
throw new Error ( "No Api apiBaseUrl" );
}
import axios from axios and add header for post request
axios . defaults . headers .post[ "Content-Type" ] = "application/json" ;
create a function createApi
that takes a path and returns an axios instance
export default const createApi = (path : string ) => {
const api = axios .create ({
baseURL : ` ${ apiBaseUrl }${ path } ` ,
timeout : 10000 ,
headers : {
"Content-Type" : "application/json" ,
} ,
});
return api;
};
add the interceptor for request and responses
export default const createApi = (path : string ) => {
// ...
api . interceptors . request .use ( async (config : InternalAxiosRequestConfig ) => {
// get session from next-auth
const session = await getSession ();
// set the access token in the header for every request after logged in
if ( session ?.accessToken) {
config . headers .set ( "Authorization" , `Bearer ${ session .accessToken } ` );
}
return config;
});
api . interceptors . response .use (
null ,
(error : AxiosError <{ statusCode : string | number ; message : string }>) => {
// handle different global error types
if ( error .message === "Network Error" ){
//handle network error
return ;
}
if ( Number ( error . response ?.status) >= 500 ) {
//handle 500 error
return ;
}
if (
Number ( error . response ?. data ?.statusCode) === 403 &&
error . response ?. data ?.message === "Invalid User Status"
) {
// handle 403 error
return ;
}
// return non global error for manual handling
throw error;
} ,
);
example for axios.ts
file will look like this
import axios , { AxiosError , InternalAxiosRequestConfig } from "axios" ;
import { getSession , signOut } from "next-auth/react" ;
import { enqueueSnackbar } from "notistack" ;
import { apiBaseUrl } from "../constants/environmentConstants" ;
if ( ! apiBaseUrl) {
throw new Error ( "No Api apiBaseUrl" );
}
axios . defaults . headers .post[ "Content-Type" ] = "application/json" ;
export default const createApi = (path : string ) => {
const api = axios .create ({
baseURL : ` ${ apiBaseUrl }${ path } ` ,
timeout : 10000 ,
headers : {
"Content-Type" : "application/json" ,
} ,
});
api . interceptors . request .use ( async (config : InternalAxiosRequestConfig ) => {
const session = await getSession ();
if ( session ?.accessToken) {
config . headers .set ( "Authorization" , `Bearer ${ session .accessToken } ` );
}
return config;
});
api . interceptors . response .use (
null ,
(error : AxiosError <{ statusCode : string | number ; message : string }>) => {
if ( error .message === "Network Error" )
return enqueueSnackbar ( "Slow Internet" , { variant : "error" });
if ( Number ( error . response ?.status) >= 500 ) {
enqueueSnackbar ( "Error" , { variant : "error" });
return ;
}
if (
Number ( error . response ?. data ?.statusCode) === 403 &&
error . response ?. data ?.message === "Invalid User Status"
) {
return signOut ({ callbackUrl : "/" });
}
throw error;
} ,
);
return api;
};
Using the axios interceptor for requests
// ... other imports
import { METHODS } from '../enums' ; // enums that have all the methods
import createApi from '../utils/axios' ;
const requestApi = createApi ( "/url" );
export const apiFunctionName = async ({
params ,
requestData
} : {
requestData : IRequestType
params : IParamType ;
}): Promise < IResponseType >> => {
const { data } = await requestApi ({
url : '/extendedUrl' ,
method : METHODS . GET , // or POST, PATCH and DELETE
daya : requestData ,
params ,
});
return data;
};
Conclusion
This is a global axios interceptor that handles requests and responses. It is a good practice to handle global errors in one place and not repeat the same code in every request.