axios에 포함된 기능으로, 요청이나 응답 전에 무엇인가를 수행해주거나, 오류 발생시에 수행할 것들을 미리 정의해 놓을 수 있는 기능
// src/components/pages/util/customApi.js
import axios from "axios";
import { refresh, refreshErrorHandle } from "./client";
const Api = axios.create({
timeout: 10000,
params: {},
});
Api.interceptors.request.use(refresh, refreshErrorHandle);
export default Api;
✔️ moment를 이용하여 로그인 해서 받아온 accessToken의 만료 시간과 현재 시간의 차이를 통해 토큰이 만료되었는지 체크
✔️ 헤더에 refreshToken, accessToken, email 담은 후 GET /api/v1/users/reissuance 요청 보내 토큰 재발급
✔️ 재발급 받은 토큰을 쿠키로 재설정 및 헤더에 재발급 받은 accessToken 저장 후 리턴
⚠️ 토큰이 만료되지 않았다면 헤더에 기존 토큰을 담아 요청 보냄
// src/components/pages/util/client.js
import axios from "axios";
import moment from "moment";
import { setCookie, getCookie, removeCookie } from "./cookie";
import jwt_decode from "jwt-decode";
const refresh = async (config) => {
const refreshToken = getCookie("refresh");
const accessToken = getCookie("access");
const decodePayload = jwt_decode(accessToken, { payload: true });
const expireAt = new Date(decodePayload.exp) * 1000;
// 토큰이 만료되었다면
if (moment(expireAt).diff(moment()) < 0 && refreshToken) {
console.log("토큰을 재발급합니다!");
const expires = moment().add('3','days').toDate();
const paths = '/';
//재발급 요청
const res = await axios.get("/api/v1/users/reissuance", {
headers: {
Authorization: `Bearer ${accessToken}`,
"Authorization-refresh": `Bearer ${refreshToken}`,
email: localStorage.getItem("email")
}
});
console.log("재발급 성공");
setCookie("access", res.headers.get("Authorization"),{paths, expires});
setCookie("refresh", res.headers.get("Authorization-refresh"),{paths, expires});
config.headers["Authorization"] = `Bearer ${getCookie("access")}`; // 토큰 교체
}
else {
config.headers["Authorization"] = `Bearer ${accessToken}`;
}
return config;
};
const refreshErrorHandle = () => {
removeCookie("refresh");
};
export { refresh, refreshErrorHandle };
customApi.js 에서 Api를 불러와 기존 axios 처럼 사용하면 된다.
import * as React from 'react';
import { Button } from 'react-bootstrap';
import Api from './customApi';
export default function Test() {
const getInfo = async () => {
await Api.get("/api/v1/users")
.then(function (response) {
alert(response.data)
})
.catch(function (err) {
console.log(err);
alert("유저 정보 조회 실패")
});
}
return (
<>
<Button
variant="primary"
onClick={getInfo}
type="submit"
sx={{ mt: 3, mb: 2 }}
>
조회 테스트
</Button>
</>
);
}