Обновить токен для ответа перехватчика запросов umi
Я использую токены в качестве авторизации, когда срок действия токена истекает, я хочу создать новый токен, используя токен обновления. Я могу сделать это с помощью библиотеки axios, но я не мог найти, как это сделать с помощью запроса umi. Кто-нибудь переводит пример кода, приведенный ниже, в пример перехватчика запросов umi?
этот ответ перехватчиков axios для моей операции обновления токена.
let isRefreshing: boolean = false;
let failedQueue: any = [];
const processQueue = (error: any, token: any = null) => {
failedQueue.forEach((prom: any) => {
if (error) {
prom.reject(error);
} else {
prom.resolve(token);
}
});
failedQueue = [];
};
axios.interceptors.response.use(
async response => {
return response;
},
async error => {
debugger;
const originalRequest = error.config;
if (error.response) {
const status = error.response.status;
const refreshToken = getStoredUserAuth().refreshToken;
if (status === 401 && !originalRequest._retry) {
if (isRefreshing) {
return new Promise(function(resolve, reject) {
failedQueue.push({ resolve, reject });
})
.then(token => {
originalRequest.headers["Authorization"] = "Bearer " + token;
return axios(originalRequest);
})
.catch(err => {
return Promise.reject(err);
});
}
originalRequest._retry = true;
isRefreshing = true;
return new Promise(function(resolve, reject) {
refreshAccessToken(refreshToken)
.then(response => {
if (response.status === 200) {
if (response.data.token) {
setAuthStatus(response.data);
axios.defaults.headers.common["Authorization"] =
"Bearer " + response.data.token;
originalRequest.headers["Authorization"] =
"Bearer " + response.data.token;
}
processQueue(null, response.data.token);
resolve(axios(originalRequest));
} else {
throw new Error();
}
})
.catch(err => {
//console.log(err);
failedQueue = [];
setUnauthStatus();
source.cancel("Session time out");
processQueue(err, null);
reject(err);
})
.then(() => {
isRefreshing = false;
});
});
}
} else {
debugger;
errorHandler(error);
}
return Promise.reject(error);
}
);
Я использую версию ant design pro V5, поэтому я попытался обновить токен с помощью запроса umi, но у меня не получилось. Как и в библиотеке axios, я не могу писать для запроса umi, я не могу установить его логику. Так может ли кто-нибудь написать тот же пример (axios.interceptors.response) выше для запроса umi?
const requestInterceptors = (url: string, options: RequestOptionsInit) => {
if (tokenService.check()) {
const headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/x-www-form-urlencoded',
'Authorization': `Bearer ${tokenService.parse()?.token}`,
};
return {
url,
options: { ...options, headers },
};
}
return {
url,
options: { ...options },
};
};
const responseInterceptors = (response: Response, options: RequestOptionsInit) => {
// I could'nt this part for refresh token like axios interceptors. I need help for that
return response;
}
export const request: RequestConfig = {
errorHandler,
requestInterceptors: [requestInterceptors],
responseInterceptors: [responseInterceptors]
};
1 ответ
Вот мое решение для обработки токена обновления в umi-request / ant-design-pro, нет необходимости в
queue
s, работает как шарм
// Neccesary imports
import type { RequestConfig } from 'umi';
import { request as requestUmi } from 'umi';
import type {
RequestInterceptor,
RequestOptionsInit,
ResponseError,
} from 'umi-request';
import Reqs from 'umi-request';
import merge from 'lodash/merge';
import cloneDeep from 'lodash/cloneDeep';
// My personal type definitions
namespace API {
export interface LoginResult {
access: string;
refresh: string;
}
}
// Part 1: "Simple" Error Handler =))
const errorHandler = (error: ResponseError) => {
console.log('HTTP ERROR', error);
throw error;
};
// Part 2: Request Interceptors, (use this instead of "headers" directly in request config)
const requestInterceptor: RequestInterceptor = (url, options) => {
return {
url,
options: merge(cloneDeep(options), {
headers: { Authorization: `Bearer ${jwt.getAccess()}` },
}),
};
};
// Part 3: Response Interceptos
const { cancel } = Reqs.CancelToken.source();
let refreshTokenRequest: Promise<API.LoginResult> | null = null;
const responseInterceptor = async (
response: Response,
options: RequestOptionsInit
) => {
const accessTokenExpired = response.status === 401;
if (accessTokenExpired) {
try {
if (!refreshTokenRequest) {
refreshTokenRequest = refreshAccessToken(jwt.getRefresh());
}
// multiple requests but "await"ing for only 1 refreshTokenRequest, because of closure
const res = await refreshTokenRequest;
if (!res) throw new Error();
if (res.access) jwt.saveAccess(res.access);
if (res.refresh) jwt.saveRefresh(res.refresh); // for ROTATE REFRESH TOKENS
return requestUmi(
response.url,
merge(cloneDeep(options), {
headers: { Authorization: `Bearer ${res.access}` },
})
);
} catch (err) {
jwt.removeAccess();
jwt.removeRefresh();
cancel('Session time out.');
throw err;
} finally {
refreshTokenRequest = null;
}
}
return response;
};
export const request: RequestConfig = {
errorHandler,
// This would fuck the refresh token logic, use requestInterceptors instead,
// because jwt.getAccess() will not being called everytime, but only the first time => lead to stale access token
// headers: { Authorization: `Bearer ${jwt.getAccess()}` },
// Handle refresh token (old): https://github.com/ant-design/ant-design-pro/issues/7159#issuecomment-680789397
// Handle refresh token (new): https://gist.github.com/paulnguyen-mn/8a5996df9b082c69f41bc9c5a8653533
requestInterceptors: [requestInterceptor],
responseInterceptors: [responseInterceptor],
};
Также размещено здесь