[英]Axios interceptor changes the POST request's content type on 401 retry
我无法弄清楚为什么 Axios 在重试时会更改我的请求的内容类型。
我正在创建一个 axios 实例,如下所示(注意全局默认标头):
import axios, { type AxiosInstance } from "axios";
const api: AxiosInstance = axios.create({
baseURL: "https://localhost:44316/",
});
export default api;
我在我的 vue3 应用程序的各种组件中导入了这个实例。 当我的令牌过期并且检测到 401 时,我使用拦截器刷新我的令牌并重试调用,如下所示(使用等待模式对多个请求进行排队并防止请求多个刷新令牌):
axios.interceptors.request.use(
(config) => {
const authStore = useAuthStore();
if (!authStore.loggedIn) {
authStore.setUserFromStorage();
if (!authStore.loggedIn) {
return config;
}
}
if (config?.headers && authStore.user.accessToken) {
config.headers = {
Authorization: `Bearer ${authStore.user.accessToken}`,
};
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
axios.interceptors.response.use(
(res) => {
return res;
},
async (err) => {
if (err.response.status === 401 && !err.config._retry) {
console.log("new token required");
err.config._retry = true;
const authStore = useAuthStore();
if (!authStore.isRefreshing) {
authStore.isRefreshing = true;
return new Promise((resolve, reject) => {
console.log("refreshing token");
axios
.post("auth/refreshToken", {
token: authStore.user?.refreshToken,
})
.then((res) => {
authStore.setUserInfo(res.data as User);
console.log("refresh token received", err.config, res.data);
resolve(axios(err.config));
})
.catch(() => {
console.log("refresh token ERROR");
authStore.logout();
})
.finally(() => {
authStore.isRefreshing = false;
});
});
} else {
// not the first request, wait for first request to finish
return new Promise((resolve, reject) => {
const intervalId = setInterval(() => {
console.log("refresh token - waiting");
if (!authStore.isRefreshing) {
clearInterval(intervalId);
console.log("refresh token - waiting resolved", err.config);
resolve(axios(err.config));
}
}, 100);
});
}
}
return Promise.reject(err);
}
);
但是当 axios 重试发布请求时,它会更改内容类型:
与原始请求相比(使用内容类型应用程序/json)
我已经阅读了所有可能找不到的帖子/示例,我对 axios 相对较新,非常感谢任何指导/示例/文档,我靠墙。
为了澄清,我使用了这个模式,因为它是我能够使用许多不同来源组合在一起的最完整的示例,如果有人有更好的模式,我将不胜感激。
这是你的问题...
config.headers = { Authorization: `Bearer ${authStore.user.accessToken}`, };
您完全覆盖了请求拦截器中的headers
object ,除了Authorization
之外,它失去了一切。
因为重放的err.config
已经将请求体序列化为字符串,删除之前计算的content-type
header 意味着客户端必须推断出纯字符串类型。
您应该做的是直接设置新的 header 值,而不覆盖整个 object。
config.headers.Authorization = `Bearer ${authStore.user.accessToken}`;
有关在不涉及间隔或超时的进行中(重新)身份验证请求后面对请求进行排队的方法,请参阅此答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.