Refactor: axios 컨피그 리팩토링, 그러나 덜 됐음.
This commit is contained in:
parent
c547860f62
commit
1547e93a84
@ -1,32 +1,27 @@
|
|||||||
import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||||
import useAuthStore from '@/stores/useAuthStore';
|
import useAuthStore from '@/stores/useAuthStore';
|
||||||
import { BaseResponse, CustomError, SuccessResponse, RefreshTokenResponse } from '@/types';
|
import { RefreshTokenResponse, ErrorResponse } from '../types';
|
||||||
|
|
||||||
const baseURL = import.meta.env.VITE_API_URL;
|
|
||||||
|
|
||||||
const api = axios.create({
|
const api = axios.create({
|
||||||
baseURL,
|
baseURL: `${import.meta.env.VITE_API_URL}/api`,
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
let isTokenRefreshing = false;
|
const refreshApi = axios.create({
|
||||||
|
baseURL: `${import.meta.env.VITE_API_URL}/api`,
|
||||||
|
withCredentials: true,
|
||||||
|
});
|
||||||
|
|
||||||
type FailedRequest = {
|
let isRefreshing = false;
|
||||||
resolve: (value?: string | undefined) => void;
|
let refreshSubscribers: Array<(token: string) => void> = [];
|
||||||
reject: (reason?: unknown) => void;
|
|
||||||
|
const subscribeTokenRefresh = (cb: (token: string) => void) => {
|
||||||
|
refreshSubscribers.push(cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
let failedQueue: FailedRequest[] = [];
|
const onRefreshed = (token: string) => {
|
||||||
|
refreshSubscribers.forEach((cb) => cb(token));
|
||||||
const processQueue = (error: Error | null, token: string | undefined = undefined): void => {
|
refreshSubscribers = [];
|
||||||
failedQueue.forEach((prom) => {
|
|
||||||
if (error) {
|
|
||||||
prom.reject(error);
|
|
||||||
} else {
|
|
||||||
prom.resolve(token);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
failedQueue = [];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
|
api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
|
||||||
@ -39,68 +34,45 @@ api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
|
|||||||
|
|
||||||
api.interceptors.response.use(
|
api.interceptors.response.use(
|
||||||
(response: AxiosResponse) => response,
|
(response: AxiosResponse) => response,
|
||||||
async (error: AxiosError<BaseResponse<CustomError>>) => {
|
(error: AxiosError<ErrorResponse>) => {
|
||||||
const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };
|
const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };
|
||||||
|
|
||||||
if (error.response?.status === 401 && !originalRequest._retry) {
|
if (error.response?.status === 401 && !originalRequest._retry) {
|
||||||
if (isTokenRefreshing) {
|
|
||||||
return new Promise<string | undefined>((resolve, reject) => {
|
|
||||||
failedQueue.push({ resolve, reject });
|
|
||||||
})
|
|
||||||
.then((token) => {
|
|
||||||
if (token && originalRequest.headers) {
|
|
||||||
originalRequest.headers.Authorization = `Bearer ${token}`;
|
|
||||||
}
|
|
||||||
return api(originalRequest);
|
|
||||||
})
|
|
||||||
.catch((err) => Promise.reject(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
originalRequest._retry = true;
|
originalRequest._retry = true;
|
||||||
isTokenRefreshing = true;
|
|
||||||
|
|
||||||
try {
|
if (isRefreshing) {
|
||||||
const response: AxiosResponse<SuccessResponse<RefreshTokenResponse>> = await api.post('/auth/reissue', null, {
|
return new Promise<void>((resolve) => {
|
||||||
withCredentials: true,
|
subscribeTokenRefresh((token: string) => {
|
||||||
|
originalRequest.headers.Authorization = `Bearer ${token}`;
|
||||||
|
resolve(api(originalRequest));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const newAccessToken = response.data.data?.accessToken;
|
|
||||||
if (!newAccessToken) {
|
|
||||||
throw new Error('Invalid token reissue response');
|
|
||||||
}
|
|
||||||
|
|
||||||
useAuthStore.getState().setLoggedIn(true, newAccessToken);
|
|
||||||
processQueue(null, newAccessToken);
|
|
||||||
|
|
||||||
const redirectUri = `/redirect/oauth2?accessToken=${newAccessToken}`;
|
|
||||||
window.location.href = redirectUri;
|
|
||||||
|
|
||||||
return Promise.reject(new Error('Redirecting to retrieve cookies'));
|
|
||||||
} catch (reissueError: unknown) {
|
|
||||||
processQueue(reissueError as Error, undefined);
|
|
||||||
console.error('토큰 재발급 실패:', reissueError);
|
|
||||||
useAuthStore.getState().clearAuth();
|
|
||||||
window.location.href = '/';
|
|
||||||
return Promise.reject(reissueError);
|
|
||||||
} finally {
|
|
||||||
isTokenRefreshing = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isRefreshing = true;
|
||||||
|
|
||||||
|
return refreshApi
|
||||||
|
.post<RefreshTokenResponse>('/auth/reissue', null, { withCredentials: true })
|
||||||
|
.then(({ data }) => {
|
||||||
|
const newAccessToken = data.accessToken;
|
||||||
|
useAuthStore.getState().setLoggedIn(true, newAccessToken);
|
||||||
|
onRefreshed(newAccessToken);
|
||||||
|
|
||||||
|
originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
|
||||||
|
return api(originalRequest);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
useAuthStore.getState().clearAuth();
|
||||||
|
console.log('리이슈 실패');
|
||||||
|
window.location.href = '/';
|
||||||
|
return Promise.reject(error);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
isRefreshing = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCommonErrors(error);
|
|
||||||
|
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCommonErrors = (error: AxiosError<BaseResponse<CustomError>>) => {
|
|
||||||
if (error.response?.status === 400) {
|
|
||||||
alert('잘못된 요청입니다. 다시 시도해 주세요.');
|
|
||||||
} else if (error.response?.status === 403) {
|
|
||||||
alert(error.response?.data?.message);
|
|
||||||
} else {
|
|
||||||
console.error('오류 발생:', error.response?.data?.message || '알 수 없는 오류');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
|
Loading…
Reference in New Issue
Block a user