68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
import type { AxiosError, AxiosRequestConfig } from 'axios';
|
|
import type { JsonValue } from 'type-fest';
|
|
import axios from 'axios';
|
|
import { isNil } from 'lodash-es';
|
|
import { router } from '@/lib/router';
|
|
import { clearTokens, doRefreshToken, getRefreshToken, getToken, setRefreshToken, setToken } from './token';
|
|
|
|
export const HEADER_API_VERSION = {
|
|
'X-Api-Version': 'latest',
|
|
};
|
|
|
|
export const axiosClient = axios.create({
|
|
baseURL: '/api/v1/',
|
|
headers: HEADER_API_VERSION,
|
|
});
|
|
|
|
axiosClient.interceptors.request.use((config) => {
|
|
const token = getToken();
|
|
if (token !== null) {
|
|
config.headers = config.headers ?? {};
|
|
config.headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
return config;
|
|
});
|
|
|
|
type RetryConfig = AxiosRequestConfig & { _retry?: boolean };
|
|
|
|
interface ResponseData {
|
|
code: number;
|
|
error_id: string;
|
|
status: string;
|
|
data: JsonValue;
|
|
}
|
|
|
|
axiosClient.interceptors.response.use(async (response) => {
|
|
const data = response.data as ResponseData;
|
|
if (data.code !== 200) {
|
|
return Promise.reject(data);
|
|
}
|
|
response.data = data.data;
|
|
return response;
|
|
}, async (error: AxiosError) => {
|
|
const originalRequest = error.config as RetryConfig | undefined;
|
|
if (!error.response || error.response.status !== 401 || !originalRequest) {
|
|
return Promise.reject(error);
|
|
}
|
|
if (error.response.status === 401 && originalRequest.url !== '/auth/refresh' && !isNil(getRefreshToken())) {
|
|
try {
|
|
const maybeRefreshTokenResponse = await doRefreshToken();
|
|
if (maybeRefreshTokenResponse.status !== 200) {
|
|
throw new Error('Failed to refresh token');
|
|
}
|
|
const { access_token, refresh_token } = maybeRefreshTokenResponse.data;
|
|
originalRequest.headers = originalRequest.headers ?? {};
|
|
originalRequest.headers.Authorization = `Bearer ${access_token}`;
|
|
setToken(access_token);
|
|
setRefreshToken(refresh_token);
|
|
return await axiosClient(originalRequest);
|
|
}
|
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
catch (e) {
|
|
// Should remove token (tokens are out of date)
|
|
clearTokens();
|
|
await router.navigate({ to: '/authorize' });
|
|
}
|
|
}
|
|
});
|