Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/components/common/TableBody/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ const TableBody = ({
key={rowIndex}
className={cn('h-16 cursor-pointer odd:bg-grey-50 hover:bg-grey-100')}
onClick={
onRowClick && type === 'list' && typeof item.설문ID === 'number'
? () => onRowClick(item.설문ID as number)
: onRowClick && type === 'list' && typeof item.식단ID === 'string'
? () => onRowClick(item.식단ID as string)
onRowClick && type === 'list' && typeof item['설문 ID'] === 'number'
? () => onRowClick(item['설문 ID'] as number)
: onRowClick &&
type === 'list' &&
typeof item['식단 ID'] === 'string'
? () => onRowClick(item['식단 ID'] as string)
: undefined
}
>
Expand Down
72 changes: 60 additions & 12 deletions src/lib/axios.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { env } from '@/lib/env';
import axios, { AxiosResponse } from 'axios';
import axios, {
AxiosError,
AxiosRequestConfig,
AxiosResponse,
InternalAxiosRequestConfig,
} from 'axios';
import { parseCookies } from 'nookies';
import { destroyTokens } from '@/utils/destroyTokens';
import { saveTokens } from '@/utils/saveTokens';
import { AUTH_API } from '@/constants/_apiPath';
import { AUTH_LINKS } from '@/constants/_auth';
Expand Down Expand Up @@ -33,11 +39,13 @@ const instance = axios.create({
});

instance.interceptors.request.use(
(config) => {
const accessToken = getAccessToken();

if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
(config: InternalAxiosRequestConfig) => {
if (typeof window !== 'undefined') {
const accessToken = getAccessToken();
if (accessToken) {
config.headers = config.headers || {};
config.headers.Authorization = `Bearer ${accessToken}`;
}
}
return config;
},
Expand All @@ -46,28 +54,54 @@ instance.interceptors.request.use(
},
);

type RefreshQueueItem = {
config: AxiosRequestConfig;
resolve: (value: AxiosResponse) => void;
reject: (reason?: AxiosError) => void;
};

let isRefreshed = false;
let refreshAndRetryQueue: RefreshQueueItem[] = [];

instance.interceptors.response.use(
(response) => {
return response;
},

async (error) => {
const originalRequest = error.config;
const originalRequest = error.config as AxiosRequestConfig & {
headers: Record<string, string>;
};

if (error.response?.status === 400) {
return Promise.resolve();
}

if (
!originalRequest ||
error.response?.status !== 410 ||
originalRequest.headers._retry !== '0'
originalRequest.headers._retry === '1'
) {
return Promise.reject(error);
}

originalRequest.headers._retry = '1';

const refreshToken = parseCookies().refreshToken;
if (!refreshToken) {
redirectToLogin();
destroyTokens();
return Promise.reject(error);
}

if (isRefreshed) {
return new Promise((resolve, reject) => {
refreshAndRetryQueue.push({ config: originalRequest, resolve, reject });
});
}

isRefreshed = true;

try {
const response = await axios.get(
`${env.BASE_API_URL}${AUTH_API.REISSUE}`,
Expand All @@ -82,13 +116,27 @@ instance.interceptors.response.use(
saveTokens({ accessToken, refreshToken: newRefreshToken });

originalRequest.headers.Authorization = `Bearer ${accessToken}`;
originalRequest.headers._retry = '1';
return await instance(originalRequest);
} else {
throw new Error('Failed to reissue tokens');

refreshAndRetryQueue.forEach(({ config, resolve, reject }) => {
config.headers = {
...config.headers,
Authorization: `Bearer ${accessToken}`,
};
instance.request(config).then(resolve).catch(reject);
});

refreshAndRetryQueue = [];

return instance(originalRequest);
}
} catch (refreshError) {
destroyTokens();
redirectToLogin();
refreshAndRetryQueue.forEach(({ reject }) => reject(error as AxiosError));
refreshAndRetryQueue = [];
return Promise.reject(refreshError);
} finally {
isRefreshed = false;
}
},
);
Expand Down
1 change: 0 additions & 1 deletion src/test.md

This file was deleted.

Loading