Refactor: Axios config 리팩토링

This commit is contained in:
jhynsoo 2024-09-19 13:10:29 +09:00
parent 97816e30db
commit eb30abefcc
2 changed files with 26 additions and 69 deletions

View File

@ -1,32 +1,17 @@
import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import useAuthStore from '@/stores/useAuthStore';
import { RefreshTokenResponse, ErrorResponse } from '../types';
import { RefreshTokenResponse } from '../types';
const REFRESH_URL = '/auth/reissue';
const api = axios.create({
baseURL: `${import.meta.env.VITE_API_URL}/api`,
baseURL: `${import.meta.env.VITE_API_URL}`,
withCredentials: true,
});
const refreshApi = axios.create({
baseURL: `${import.meta.env.VITE_API_URL}/api`,
withCredentials: true,
});
let isRefreshing = false;
let refreshSubscribers: Array<(token: string) => void> = [];
const subscribeTokenRefresh = (cb: (token: string) => void) => {
refreshSubscribers.push(cb);
};
const onRefreshed = (token: string) => {
refreshSubscribers.forEach((cb) => cb(token));
refreshSubscribers = [];
};
api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
const accessToken = useAuthStore.getState().accessToken;
if (accessToken && config.headers) {
if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
}
return config;
@ -34,45 +19,28 @@ api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
api.interceptors.response.use(
(response: AxiosResponse) => response,
(error: AxiosError<ErrorResponse>) => {
const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
if (isRefreshing) {
return new Promise<void>((resolve) => {
subscribeTokenRefresh((token: string) => {
originalRequest.headers.Authorization = `Bearer ${token}`;
resolve(api(originalRequest));
});
});
(error: AxiosError) => {
if (error.response?.status !== 401 || error.request.responseURL?.includes(REFRESH_URL)) {
return Promise.reject(error);
}
isRefreshing = true;
return refreshApi
.post<RefreshTokenResponse>('/auth/reissue', null, { withCredentials: true })
return api
.post<RefreshTokenResponse>(REFRESH_URL)
.then(({ data }) => {
const newAccessToken = data.accessToken;
useAuthStore.getState().setLoggedIn(true, newAccessToken);
onRefreshed(newAccessToken);
originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
return api(originalRequest);
console.log(data);
const { accessToken } = data;
useAuthStore.getState().setLoggedIn(true, accessToken);
if (error.config) {
return api(error.config);
}
return Promise.reject(error);
})
.catch(() => {
.catch((error) => {
useAuthStore.getState().clearAuth();
console.log('리이슈 실패');
window.location.href = '/';
return Promise.reject(error);
})
.finally(() => {
isRefreshing = false;
});
}
return Promise.reject(error);
}
);
export default api;

View File

@ -18,7 +18,7 @@ export default function Home() {
});
}
const handleGoogleSignIn = () => {
window.location.href = `${BASE_URL}/api/login/oauth2/authorization/google`;
window.location.href = `${BASE_URL}/login/oauth2/authorization/google`;
};
return (
@ -43,17 +43,6 @@ export default function Home() {
</div>
{!isLoggedIn ? (
// <Link
// to={`${BASE_URL}/api/login/oauth2/authorization/google`}
// // onClick={handleGoogleSignIn}
// className="mb-4 transition hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-gray-300 active:opacity-80"
// >
// <img
// src={GoogleLogo}
// alt="Sign in with Google"
// className="h-auto w-full"
// />
// </Link>
<button
onClick={handleGoogleSignIn}
className="mb-4 transition hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-gray-300 active:opacity-80"