import axios from "axios"; import { useNavigate } from "react-router-dom"; import axiosRetry from "axios-retry"; import showToast from "../services/toastService"; const base_Url = import.meta.env.VITE_BASE_URL; export const axiosClient = axios.create({ baseURL: base_Url, // Your Web API URL withCredentials: false, // Required if the API uses cookies headers: { "Content-Type": "application/json", // Specify the content type }, }); axiosRetry(axiosClient, { retries: 3 }); // Request interceptor to add Bearer token axiosClient.interceptors.request.use( async (config) => { if (config.authRequired) { const token = localStorage.getItem("jwtToken"); if (token) { config.headers["Authorization"] = `Bearer ${token}`; } } return config; }, (error) => { return Promise.reject(error); } ); // // Response interceptor to handle responses globally (optional) // Add an interceptor to handle expired tokens axiosClient.interceptors.response.use( (response) => response, async (error) => { // debugger; const originalRequest = error.config; if (error.code === "ERR_CONNECTION_REFUSED") { console.error("Connection refused. Please ensure the server is running."); showToast( "Unable to connect to the server. Please try again later.", "error" ); } if (error.code === "ERR_NETWORK") { console.error( "Unable to connect server. Please ensure the server is running." ); showToast("Server is unreachable. Try again later.!", "error"); originalRequest._retry = false; redirectToLogin(); return Promise.reject(error); } else if (error.code === "ECONNABORTED") { console.error("Request timed out."); showToast("The request took too long. Please try again later.", "error"); } else { console.error("An error occurred:", error.message); } if ( error.response && error.response.status === 401 && !originalRequest._retry ) { originalRequest._retry = true; try { // debugger; // Get the refresh token from secure storage const refreshToken = localStorage.getItem("refreshToken"); if (!refreshToken) { // Redirect to login if refresh token is not available redirectToLogin(); return Promise.reject(error); } // Make a request to refresh the access token const response = await axiosClient.post("/api/Auth/refresh-token", { token: localStorage.getItem("jwtToken"), refreshToken: refreshToken, }); const { token } = response.data.data; // Save the new access token localStorage.setItem("jwtToken", token); localStorage.setItem("refreshToken", response.data.data.refreshToken); // Update the original request with the new token originalRequest.headers["Authorization"] = `Bearer ${token}`; // Retry the original request return api(originalRequest); } catch (err) { // Redirect to login if token refresh fails redirectToLogin(); return Promise.reject(err); } } return Promise.reject(error); } ); // Generic API Call const apiRequest = async (method, url, data = {}, config = {}) => { try { const response = await axiosClient({ method, url, data: method !== "get" ? data : undefined, params: method === "get" ? data : undefined, ...config, }); return response.data; } catch (error) { throw error; } }; export const api = { // For public routes like login, set authRequired: false postPublic: (url, data = {}, customHeaders = {}) => apiRequest("post", url, data, { headers: { ...customHeaders }, authRequired: false, }), // For protected routes, authRequired defaults to true get: (url, params = {}, customHeaders = {}) => apiRequest("get", url, params, { headers: { ...customHeaders }, authRequired: true, }), post: (url, data = {}, customHeaders = {}) => apiRequest("post", url, data, { headers: { ...customHeaders }, authRequired: true, }), put: (url, data = {}, customHeaders = {}) => apiRequest("put", url, data, { headers: { ...customHeaders }, authRequired: true, }), delete: (url, data = {}, customHeaders = {}) => apiRequest("delete", url, data, { headers: { ...customHeaders }, authRequired: true, }), }; //export default axiosClient; function redirectToLogin() { // window.location.href = "/auth/login"; }