89 lines
1.9 KiB
TypeScript
89 lines
1.9 KiB
TypeScript
import axios, { AxiosError, InternalAxiosRequestConfig } from "axios";
|
|
|
|
export const baseURL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3344";
|
|
|
|
export const api = axios.create({
|
|
baseURL,
|
|
withCredentials: true,
|
|
});
|
|
|
|
interface CustomAxiosRequestConfig extends InternalAxiosRequestConfig {
|
|
_retry?: boolean;
|
|
}
|
|
|
|
interface QueueItem {
|
|
resolve: () => void;
|
|
reject: (error: unknown) => void;
|
|
}
|
|
|
|
let isRefreshing = false;
|
|
let queue: QueueItem[] = [];
|
|
|
|
const processQueue = (error: unknown = null) => {
|
|
queue.forEach((p) => {
|
|
if (error) p.reject(error);
|
|
else p.resolve();
|
|
});
|
|
queue = [];
|
|
};
|
|
|
|
const skipRefreshUrls = [
|
|
"/auth/signin",
|
|
"/auth/signup",
|
|
"/auth/logout",
|
|
"/auth/refresh",
|
|
"/auth/forgot-password",
|
|
"/auth/token/create",
|
|
"/auth/token/verify",
|
|
];
|
|
|
|
api.interceptors.response.use(
|
|
(res) => res,
|
|
async (err: AxiosError) => {
|
|
const originalRequest = err.config as CustomAxiosRequestConfig;
|
|
|
|
const url = originalRequest?.url || "";
|
|
|
|
const shouldSkip = skipRefreshUrls?.some((path) =>
|
|
url?.includes(path)
|
|
);
|
|
|
|
if (
|
|
err.response?.status === 401 &&
|
|
originalRequest &&
|
|
!originalRequest._retry &&
|
|
!shouldSkip
|
|
) {
|
|
if (isRefreshing) {
|
|
return new Promise((resolve, reject) => {
|
|
queue.push({
|
|
resolve: () => resolve(api(originalRequest)),
|
|
reject: (queueErr) => reject(queueErr),
|
|
});
|
|
});
|
|
}
|
|
|
|
originalRequest._retry = true;
|
|
isRefreshing = true;
|
|
|
|
try {
|
|
await axios.post(`${baseURL}/auth/refresh`, {}, { withCredentials: true });
|
|
|
|
processQueue(null);
|
|
|
|
return api(originalRequest);
|
|
} catch (refreshErr) {
|
|
processQueue(refreshErr);
|
|
|
|
window.location.href = "/auth/signin"
|
|
|
|
return Promise.reject(refreshErr);
|
|
} finally {
|
|
isRefreshing = false;
|
|
}
|
|
}
|
|
|
|
return Promise.reject(err);
|
|
}
|
|
);
|