From bee1bc9b0bbc9da46095b43cf4c2dce0c733ef22 Mon Sep 17 00:00:00 2001 From: cjeongmin <cjeongmin27@gmail.com> Date: Thu, 16 May 2024 21:29:58 +0900 Subject: [PATCH] feat: Add axios interceptor setup (#83) --- src/app/layout.tsx | 1 + src/app/lib/axios.ts | 66 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/app/lib/axios.ts diff --git a/src/app/layout.tsx b/src/app/layout.tsx index fc4ca1d38d..109c3b843c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata } from 'next'; import { Inter } from 'next/font/google'; import React from 'react'; import './globals.scss'; +import './lib/axios'; import { AuthProvider, diff --git a/src/app/lib/axios.ts b/src/app/lib/axios.ts new file mode 100644 index 0000000000..0963a9548b --- /dev/null +++ b/src/app/lib/axios.ts @@ -0,0 +1,66 @@ +'use client'; + +import axios, { + type AxiosError, + type AxiosRequestConfig, + type AxiosResponse, +} from 'axios'; +import { useRouter } from 'next/navigation'; + +import { getUserData, postTokenRefresh, useAuthActions } from '@/features/auth'; +import { load } from '@/shared/storage'; + +let isRefreshing = false; + +axios.interceptors.response.use( + (response: AxiosResponse) => response, + async (error: AxiosError) => { + const router = useRouter(); + const { login, logout, setAuthUserData } = useAuthActions(); + + const { config, response } = error; + const originalRequest = config as AxiosRequestConfig; + + const refreshToken = load<string>({ + type: 'local', + key: 'refreshToken', + }); + + if ( + response != null && + refreshToken != null && + response.status === 401 && + !isRefreshing + ) { + isRefreshing = true; + + return await new Promise((resolve, reject) => { + postTokenRefresh(refreshToken) + .then(({ data }) => { + if (originalRequest.headers != null) + originalRequest.headers.Authorization = `Bearer ${data.accessToken}`; + + login(data); + getUserData() + .then(({ data: user }) => { + setAuthUserData(user); + }) + .catch(err => { + console.error(err); + }); + + resolve(axios(originalRequest)); + }) + .catch(err => { + router.push('/'); + logout(); + reject(err); + }) + .finally(() => { + isRefreshing = false; + }); + }); + } + return await Promise.reject(error); + }, +);