我的问题与
customAxios.interceptors.response.use
有关。我来这里的目的是;如果令牌过期并且出现 401 错误,请在出现 401 错误时再次发出请求,并将新令牌写入标头。另一方面,如果我收到除 401 错误之外的错误,请显示 error.response.data
。你认为这个逻辑设置正确吗?我尝试测试,但我不确定,尤其是 401 错误情况
import axios from "axios";
import { LoginAPI } from "../playwright/tests/login/login.api";
import { test } from "@playwright/test"
import {configEnv} from "../config/config"
test.beforeAll(async () => {
await LoginAPI.API.Signin.run()
});
const customAxios = axios.create({
baseURL: configEnv.apiBaseURL
});
customAxios.interceptors.request.use(
async (config) => {
if (config.headers) {
config.headers['Authorization'] = `Bearer ${LoginAPI.States.token}`;
return config;
}
return config;
},
(error) => {
Promise.reject(error);
}
);
customAxios.interceptors.response.use(
function(response) {
return response;
},
async function(error) {
if (401 === error.response.status) {
await LoginAPI.API.Signin.run()
customAxios.defaults.headers.common['Authorization'] = `Bearer ${LoginAPI.States.token}`
} else {
return Promise.reject(error.response.data);
}
}
);
export default customAxios
我建议您将令牌存储在 localStorage 中,然后在刷新后替换它。这样您就可以在 API 类中的一个位置设置令牌。
import axios from "axios";
export const ApiClient = () => {
// Create a new axios instance
const api = axios.create({
baseURL: "URL",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
// Add a request interceptor to add the JWT token to the authorization header
api.interceptors.request.use(
(config) => {
const token = sessionStorage.getItem("jwtToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// Add a response interceptor to refresh the JWT token if it's expired
api.interceptors.response.use(
(response) => response,
(error) => {
const originalRequest = error.config;
// If the error is a 401 and we have a refresh token, refresh the JWT token
if (
error.response.status === 401 &&
sessionStorage.getItem("refreshToken")
) {
const refreshToken = sessionStorage.getItem("refreshToken");
let data = JSON.stringify({
refresh_token: refreshToken,
});
post("/refreshToken", data)
.then((response) => {
sessionStorage.setItem("jwtToken", response.token);
sessionStorage.setItem("refreshToken", response.refresh_token);
// Re-run the original request that was intercepted
originalRequest.headers.Authorization = `Bearer ${response.token}`;
api(originalRequest)
.then((response) => {
return response.data;
})
.catch((error) => {
console.log(error);
});
// return api(originalRequest)
})
.catch((err) => {
// If there is an error refreshing the token, log out the user
console.log(err);
});
}
// Return the original error if we can't handle it
return Promise.reject(error);
}
);
const login = (email, password) => {
return api
.post("/authentication_token", { email, password })
.then(({ data }) => {
// Store the JWT and refresh tokens in session storage
sessionStorage.setItem("jwtToken", data.token);
sessionStorage.setItem("refreshToken", data.refresh_token);
})
.catch((err) => {
// Return the error if the request fails
return err;
});
};
const get = (path) => {
return api.get(path).then((response) => response.data);
};
const post = (path, data) => {
return api.post(path, data).then((response) => response.data);
};
const put = (path, data) => {
return api.put(path, data).then((response) => response.data);
};
const del = (path) => {
return api.delete(path).then((response) => response);
};
return {
login,
get,
post,
put,
del,
};
};
最好的, 克里斯
这是从 @cLx 的版本修改而来的另一个版本。它周围没有包装的 ApiClient,并且它可以防止触发多个 /refresh-token 调用。此示例中的一个烦恼是我基本上使用两个术语来表示“access_token”。它在存储中的关键是“令牌”,但作为整个代码中的变量,它被称为
access_token
。
import axios from 'axios';
const axiosInstance = axios.create({
baseURL: process.env.REACT_APP_API_BASE_URL,
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
const refreshTheToken = async (data) => {
await axiosInstance.post("/refresh_token", data)
.then((response) => {
const access_token = JSON.stringify(response.data.access_token);
const refresh_token = JSON.stringify(response.data.refresh_token);
sessionStorage.setItem("token", access_token);
sessionStorage.setItem("refresh_token", refresh_token);
return access_token;
})
.catch((err) => {
// If there is an error refreshing the token, log out the user
console.log(err);
return Promise.reject(err);
});
}
// Add a request interceptor to add the JWT token to the authorization header
axiosInstance.interceptors.request.use(
(config) => {
const token = JSON.parse(sessionStorage.getItem("token"));
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// Add a response interceptor to refresh the JWT token if it's expired
axiosInstance.interceptors.response.use(
(response) => {
return response
},
async (error) => {
const originalRequest = error.config;
// If the error is a 401 and we have a refresh token, refresh the JWT token
if (error.response.status === 401 && sessionStorage.getItem("refresh_token")) {
const refreshToken = JSON.parse(sessionStorage.getItem("refresh_token"));
let data = JSON.stringify({
refresh_token: refreshToken,
});
const access_token = await refreshTheToken(data)
// Re-run the original request that was intercepted
originalRequest.headers.Authorization = `Bearer ${access_token}`;
return axiosInstance(originalRequest);
}
// Return the original error if we can't handle it
return Promise.reject(error);
}
);
export default axiosInstance;