如何使用 axios 为多个请求刷新身份验证令牌逻辑?
How can I do refresh auth token logiс with axios for multiple requests?
我试图这样做,但对于三个请求,它发送了三个刷新请求:
- 1、2、3 失败,返回 401
- 刷新成功,1次成功,2、3次失败
- 刷新成功,2次成功,3次失败
- 刷新成功3次成功
我无法在移动设备上施加那么大的负载(即使没有 "refail" 只有 3 次刷新)
这是我的代码:
function requestRefreshToken(refreshToken, accessToken) {
return axios
.create({
baseURL: apiUrl + Endpoints.AUTH.REFRESH,
skipAuthRefresh: true,
headers: {
'Accept-Language': 'ru',
'User-Agent': `${Platform.OS} ${packageJson.version}`,
Authorization: accessToken,
},
})
.post(
'',
{
grant_type: GrantTypes.REFRESH_TOKEN,
refresh_token: refreshToken,
client_id: Client.id,
client_secret: Client.secret,
},
{ validateStatus },
);
}
const refreshAuthLogic = async failedRequest =>
Keychain.getCredentials()
.then(old => requestRefreshToken(old.refreshToken, old.accessToken))
.then(({ data: credentials }) => {
failedRequest.config.headers.Authorization = `${credentials.token_type} ${
credentials.access_token
}`;
return Keychain.setCredentials(credentials);
});
createAuthRefreshInterceptor(axios, refreshAuthLogic, {
retryInstance: axios,
skipWhileRefreshing: true,
onRetry: function(config) {
return Keychain.getCredentials().then(({ accessToken }) =>
axios({
...config,
header: { ...config.headers, Authorization: accessToken },
}),
);
},
});
axios.interceptors.response.use(
r => r,
request => {
if (request.response.status === 401) {
return Keychain.getCredentials().then(({ accessToken }) =>
axios({
...request.config,
header: { ...request.config.headers, Authorization: accessToken },
}),
);
}
},
);
解决了!似乎没有失败的请求队列就无法解决它(https://gist.github.com/mkjiau/650013a99c341c9f23ca00ccb213db1c
这是我实现它的一种快速方法。
我发现对代码进行推理要简单一些。
我已经从这个解决方案中改编了它:
let refreshTokenPromise: null | Promise < any > ;
instance.interceptors.response.use(r => {
const {
data
} = r;
if (data.errors && data.errors[0].message === "AUTH_EXPIRED") {
if (!refreshTokenPromise) {
refreshTokenPromise = fetchRefreshToken().then(data => {
refreshTokenPromise = null;
return data;
});
}
return refreshTokenPromise.then(token => {
if (r.config.headers) r.config.headers["Authorization"] = token;
return instance.request(r.config);
});
}
return r;
});
我试图这样做,但对于三个请求,它发送了三个刷新请求:
- 1、2、3 失败,返回 401
- 刷新成功,1次成功,2、3次失败
- 刷新成功,2次成功,3次失败
- 刷新成功3次成功
我无法在移动设备上施加那么大的负载(即使没有 "refail" 只有 3 次刷新)
这是我的代码:
function requestRefreshToken(refreshToken, accessToken) {
return axios
.create({
baseURL: apiUrl + Endpoints.AUTH.REFRESH,
skipAuthRefresh: true,
headers: {
'Accept-Language': 'ru',
'User-Agent': `${Platform.OS} ${packageJson.version}`,
Authorization: accessToken,
},
})
.post(
'',
{
grant_type: GrantTypes.REFRESH_TOKEN,
refresh_token: refreshToken,
client_id: Client.id,
client_secret: Client.secret,
},
{ validateStatus },
);
}
const refreshAuthLogic = async failedRequest =>
Keychain.getCredentials()
.then(old => requestRefreshToken(old.refreshToken, old.accessToken))
.then(({ data: credentials }) => {
failedRequest.config.headers.Authorization = `${credentials.token_type} ${
credentials.access_token
}`;
return Keychain.setCredentials(credentials);
});
createAuthRefreshInterceptor(axios, refreshAuthLogic, {
retryInstance: axios,
skipWhileRefreshing: true,
onRetry: function(config) {
return Keychain.getCredentials().then(({ accessToken }) =>
axios({
...config,
header: { ...config.headers, Authorization: accessToken },
}),
);
},
});
axios.interceptors.response.use(
r => r,
request => {
if (request.response.status === 401) {
return Keychain.getCredentials().then(({ accessToken }) =>
axios({
...request.config,
header: { ...request.config.headers, Authorization: accessToken },
}),
);
}
},
);
解决了!似乎没有失败的请求队列就无法解决它(https://gist.github.com/mkjiau/650013a99c341c9f23ca00ccb213db1c
这是我实现它的一种快速方法。
我发现对代码进行推理要简单一些。
我已经从这个解决方案中改编了它:
let refreshTokenPromise: null | Promise < any > ;
instance.interceptors.response.use(r => {
const {
data
} = r;
if (data.errors && data.errors[0].message === "AUTH_EXPIRED") {
if (!refreshTokenPromise) {
refreshTokenPromise = fetchRefreshToken().then(data => {
refreshTokenPromise = null;
return data;
});
}
return refreshTokenPromise.then(token => {
if (r.config.headers) r.config.headers["Authorization"] = token;
return instance.request(r.config);
});
}
return r;
});