1- import axios , { AxiosError } from "axios" ;
1+ import axios , { AxiosError , InternalAxiosRequestConfig } from "axios" ;
22import { Cookies } from "react-cookie" ;
3- import { reissueToken } from "./auth" ;
3+ import { ReissueToken } from "./auth" ;
4+ import * as Sentry from "@sentry/nextjs" ;
5+
6+ type ErrorResponseData = {
7+ message ?: string ;
8+ status ?: number ;
9+ } ;
10+
11+ type RetryableRequestConfig = InternalAxiosRequestConfig & {
12+ _retry ?: boolean ;
13+ } ;
414
515export const instance = axios . create ( {
616 baseURL : process . env . NEXT_PUBLIC_BASE_URL ,
7- timeout : 10_000 ,
17+ timeout : 10_000
818} ) ;
919
1020const cookie = new Cookies ( ) ;
1121
22+ const clearAuthCookies = ( ) => {
23+ cookie . remove ( "access_token" , { path : "/" } ) ;
24+ cookie . remove ( "refresh_token" , { path : "/" } ) ;
25+ cookie . remove ( "authority" , { path : "/" } ) ;
26+ } ;
27+
28+ const redirectTo = ( path : string ) => {
29+ if ( typeof window === "undefined" ) {
30+ return ;
31+ }
32+
33+ if ( window . location . pathname !== path ) {
34+ window . location . href = path ;
35+ }
36+ } ;
37+
1238instance . interceptors . request . use (
1339 config => {
1440 const accessToken = cookie . get ( "access_token" ) ;
1541 const returnConfig = {
16- ...config ,
42+ ...config
1743 } ;
44+
45+ returnConfig . headers = returnConfig . headers ?? { } ;
46+
1847 if ( accessToken ) {
19- returnConfig . headers ! . Authorization = `Bearer ${ accessToken } ` ;
48+ returnConfig . headers . Authorization = `Bearer ${ accessToken } ` ;
2049 }
50+
2151 return returnConfig ;
2252 } ,
2353 ( error : AxiosError ) => {
@@ -27,73 +57,86 @@ instance.interceptors.request.use(
2757
2858instance . interceptors . response . use (
2959 async response => response ,
30- async ( error : AxiosError < AxiosError > ) => {
60+ async ( error : AxiosError < ErrorResponseData > ) => {
3161 console . error ( error ) ;
32- if ( axios . isAxiosError ( error ) && error . response ) {
33- const {
34- config,
35- response : { data } ,
36- } = error ;
37- const refreshToken = cookie . get ( "refresh_token" ) ;
38- const { response, message } = error ;
39-
40- if ( response . data . status && response . data . status > 500 ) {
41- window . location . href = "/serverCheck" ;
42- throw error ;
43- }
62+ Sentry . captureException ( error ) ;
4463
45- if ( response . data . status === null ) {
46- return ;
47- }
64+ if ( ! axios . isAxiosError ( error ) || ! error . response ) {
65+ throw error ;
66+ }
67+
68+ const { config, response } = error ;
69+ const refreshToken = cookie . get ( "refresh_token" ) ;
70+ const status = response . status ?? response . data ?. status ;
71+ const responseMessage = response . data ?. message ;
72+ Sentry . captureMessage ( responseMessage ?? error . message ) ;
73+ const originalRequest = config as RetryableRequestConfig | undefined ;
74+ const isReissueRequest = originalRequest ?. url ?. includes ( "/auth/reissue" ) ;
75+ const isAuthError =
76+ status === 401 ||
77+ status === 403 ||
78+ responseMessage === "Invalid Token" ||
79+ responseMessage === "Token Expired" ;
80+
81+ if ( ( response . data ?. status ?? response . status ) >= 500 ) {
82+ redirectTo ( "/serverCheck" ) ;
83+ throw error ;
84+ }
85+
86+ if ( ! isAuthError ) {
87+ throw error ;
88+ }
89+
90+ if ( ! originalRequest || originalRequest . _retry || isReissueRequest ) {
91+ clearAuthCookies ( ) ;
92+ redirectTo ( "/" ) ;
93+ throw error ;
94+ }
95+
96+ if ( ! refreshToken ) {
97+ clearAuthCookies ( ) ;
98+ redirectTo ( "/" ) ;
99+ throw error ;
100+ }
101+
102+ originalRequest . _retry = true ;
103+ cookie . remove ( "access_token" , { path : "/" } ) ;
104+
105+ try {
106+ const res = await ReissueToken ( refreshToken ) ;
107+ const accessExpired = new Date ( res . access_expires_at ) ;
108+ const refreshExpired = new Date ( res . refresh_expires_at ) ;
109+
110+ cookie . set ( "access_token" , res . access_token , {
111+ expires : accessExpired ,
112+ path : "/"
113+ } ) ;
114+ cookie . set ( "refresh_token" , res . refresh_token , {
115+ expires : refreshExpired ,
116+ path : "/"
117+ } ) ;
118+ cookie . set ( "authority" , res . authority , { path : "/" } ) ;
119+
120+ originalRequest . headers = originalRequest . headers ?? { } ;
121+ originalRequest . headers . Authorization = `Bearer ${ res . access_token } ` ;
122+
123+ return instance ( originalRequest ) ;
124+ } catch ( reissueError ) {
125+ const reissueAxiosError = reissueError as AxiosError < ErrorResponseData > ;
126+ const reissueStatus =
127+ reissueAxiosError . response ?. status ??
128+ reissueAxiosError . response ?. data ?. status ;
48129
49130 if (
50- response . data . message === "Invalid Token" ||
51- response . data . message === "Token Expired" ||
52- message === "Request failed with status code 403"
131+ reissueStatus === 404 ||
132+ reissueStatus === 401 ||
133+ reissueStatus === 403
53134 ) {
54- const originalRequest = config ;
55-
56- if ( refreshToken ) {
57- cookie . remove ( "access_token" ) ;
58- reissueToken ( refreshToken )
59- . then ( res => {
60- const accessExpired = new Date ( res . access_expires_at ) ;
61- const refreshExpired = new Date ( res . refresh_expires_at ) ;
62-
63- cookie . set ( "access_token" , res . access_token , {
64- expires : accessExpired ,
65- path : "/" ,
66- } ) ;
67- cookie . set ( "refresh_token" , res . refresh_token , {
68- expires : refreshExpired ,
69- path : "/" ,
70- } ) ;
71- cookie . set ( "authority" , res . authority ) ;
72- if ( originalRequest ! . headers ) {
73- originalRequest ! . headers . Authorization = `Bearer ${ res . access_token } ` ;
74- }
75- return axios ( originalRequest ! ) ;
76- } )
77- . catch ( ( err : AxiosError < AxiosError > ) => {
78- const { response : errorResponse } = err ;
79-
80- if (
81- errorResponse ?. data . status === 404 ||
82- errorResponse ?. data . status === 401
83- ) {
84- cookie . remove ( "access_token" ) ;
85- cookie . remove ( "refresh_token" ) ;
86- window . location . href = "/" ;
87- }
88- } ) ;
89- } else {
90- cookie . remove ( "access_token" ) ;
91- cookie . remove ( "refresh_token" ) ;
92- window . location . href = "/" ;
93- }
94- } else {
95- throw error ;
135+ clearAuthCookies ( ) ;
136+ redirectTo ( "/" ) ;
96137 }
138+
139+ throw reissueError ;
97140 }
98141 }
99142) ;
0 commit comments