1- import axios , { type AxiosInstance } from "axios" ;
2- import { reissueAccessTokenApi } from "@/lib/api/auth" ;
3- import { isTokenExpired } from "@/lib/utils/jwtUtils" ;
4- import {
5- loadAccessToken ,
6- loadRefreshToken ,
7- removeAccessToken ,
8- removeRefreshToken ,
9- saveAccessToken ,
10- } from "@/lib/utils/localStorage" ;
1+ import axios , { type AxiosInstance , type InternalAxiosRequestConfig } from "axios" ;
2+ import { clearSession , ensureSessionToken , reissueAccessTokenIfPossible } from "@/lib/auth/session" ;
113
124const convertToBearer = ( token : string ) => `Bearer ${ token } ` ;
135
@@ -22,34 +14,24 @@ export const axiosInstance: AxiosInstance = axios.create({
2214 withCredentials : true ,
2315} ) ;
2416
17+ const redirectToLogin = ( ) => {
18+ if ( typeof window !== "undefined" && window . location . pathname !== "/auth/login" ) {
19+ window . location . replace ( "/auth/login" ) ;
20+ }
21+ } ;
22+
2523axiosInstance . interceptors . request . use (
2624 async ( config ) => {
2725 const newConfig = { ...config } ;
28- let accessToken : string | null = loadAccessToken ( ) ;
29-
30- if ( accessToken === null || isTokenExpired ( accessToken ) ) {
31- const refreshToken = loadRefreshToken ( ) ;
32- if ( refreshToken === null || isTokenExpired ( refreshToken ) ) {
33- removeAccessToken ( ) ;
34- removeRefreshToken ( ) ;
35- return config ;
36- }
26+ const accessToken = await ensureSessionToken ( ) ;
3727
38- await reissueAccessTokenApi ( refreshToken )
39- . then ( ( res ) => {
40- accessToken = res . data . accessToken ;
41- saveAccessToken ( accessToken ) ;
42- } )
43- . catch ( ( err ) => {
44- removeAccessToken ( ) ;
45- removeRefreshToken ( ) ;
46- console . error ( "인증 토큰 갱신중 오류가 발생했습니다" , err ) ;
47- } ) ;
28+ if ( ! accessToken ) {
29+ clearSession ( ) ;
30+ redirectToLogin ( ) ;
31+ return Promise . reject ( new Error ( "로그인이 필요합니다." ) ) ;
4832 }
4933
50- if ( accessToken !== null ) {
51- newConfig . headers . Authorization = convertToBearer ( accessToken ) ;
52- }
34+ newConfig . headers . Authorization = convertToBearer ( accessToken ) ;
5335 return newConfig ;
5436 } ,
5537 ( error ) => Promise . reject ( error ) ,
@@ -58,37 +40,25 @@ axiosInstance.interceptors.request.use(
5840axiosInstance . interceptors . response . use (
5941 ( response ) => response ,
6042 async ( error ) => {
61- const newError = { ...error } ;
62- if ( error . response ?. status === 401 || error . response ?. status === 403 ) {
63- const refreshToken = loadRefreshToken ( ) ;
64-
65- if ( refreshToken === null || isTokenExpired ( refreshToken ) ) {
66- removeAccessToken ( ) ;
67- removeRefreshToken ( ) ;
68- throw newError ;
69- }
70-
71- try {
72- const newAccessToken = await reissueAccessTokenApi ( refreshToken ) . then ( ( res ) => res . data . accessToken ) ;
73- saveAccessToken ( newAccessToken ) ;
43+ const status = error . response ?. status ;
44+ const originalRequest = error . config as ( InternalAxiosRequestConfig & { _retry ?: boolean } ) | undefined ;
7445
75- if ( error ?. config . headers === undefined ) {
76- newError . config . headers = { } ;
77- }
78- newError . config . headers . Authorization = convertToBearer ( newAccessToken ) ;
46+ if ( ( status === 401 || status === 403 ) && originalRequest && ! originalRequest . _retry ) {
47+ originalRequest . _retry = true ;
7948
80- return await axios . request ( newError . config ) ;
81- } catch ( _err ) {
82- removeAccessToken ( ) ;
83- removeRefreshToken ( ) ;
84- throw Error ( "로그인이 필요합니다" ) ;
49+ const reissuedAccessToken = await reissueAccessTokenIfPossible ( ) ;
50+ if ( reissuedAccessToken ) {
51+ originalRequest . headers = originalRequest . headers ?? { } ;
52+ originalRequest . headers . Authorization = convertToBearer ( reissuedAccessToken ) ;
53+ return axiosInstance ( originalRequest ) ;
8554 }
86- } else {
87- throw newError ;
8855 }
56+
57+ if ( status === 401 || status === 403 ) {
58+ clearSession ( ) ;
59+ redirectToLogin ( ) ;
60+ }
61+
62+ return Promise . reject ( error ) ;
8963 } ,
9064) ;
91-
92- export const publicAxiosInstance : AxiosInstance = axios . create ( {
93- baseURL : API_SERVER_URL ,
94- } ) ;
0 commit comments