fix(web): stream api support refresh token
This commit is contained in:
@@ -1,8 +1,47 @@
|
|||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import i18n from '@/i18n'
|
import i18n from '@/i18n'
|
||||||
import { cookieUtils } from './request'
|
import { cookieUtils } from './request'
|
||||||
|
import { refreshToken } from '@/api/user'
|
||||||
|
import { clearAuthData } from './auth'
|
||||||
const API_PREFIX = '/api'
|
const API_PREFIX = '/api'
|
||||||
|
|
||||||
|
// Token refresh state
|
||||||
|
let isRefreshing = false;
|
||||||
|
let refreshPromise: Promise<string> | null = null;
|
||||||
|
|
||||||
|
// Refresh token function for SSE
|
||||||
|
const refreshTokenForSSE = async (): Promise<string> => {
|
||||||
|
if (isRefreshing && refreshPromise) {
|
||||||
|
return refreshPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
isRefreshing = true;
|
||||||
|
refreshPromise = (async () => {
|
||||||
|
try {
|
||||||
|
const refresh_token = cookieUtils.get('refreshToken');
|
||||||
|
if (!refresh_token) {
|
||||||
|
throw new Error(i18n.t('common.refreshTokenNotExist'));
|
||||||
|
}
|
||||||
|
const response: any = await refreshToken();
|
||||||
|
const newToken = response.access_token;
|
||||||
|
cookieUtils.set('authToken', newToken);
|
||||||
|
return newToken;
|
||||||
|
} catch (error) {
|
||||||
|
clearAuthData();
|
||||||
|
message.warning(i18n.t('common.loginExpired'));
|
||||||
|
if (!window.location.hash.includes('#/login')) {
|
||||||
|
window.location.href = `/#/login`;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
isRefreshing = false;
|
||||||
|
refreshPromise = null;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return refreshPromise;
|
||||||
|
};
|
||||||
|
|
||||||
export interface SSEMessage {
|
export interface SSEMessage {
|
||||||
event?: string
|
event?: string
|
||||||
data?: string | object
|
data?: string | object
|
||||||
@@ -66,11 +105,8 @@ function parseDataContent(dataContent: string): string | object {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const makeSSERequest = async (url: string, data: any, token: string, config = { headers: {} }) => {
|
||||||
export const handleSSE = async (url: string, data: any, onMessage?: (data: SSEMessage[]) => void, config = { headers: {} }) => {
|
return fetch(`${API_PREFIX}${url}`, {
|
||||||
try {
|
|
||||||
const token = cookieUtils.get('authToken');
|
|
||||||
const response = await fetch(`${API_PREFIX}${url}`, {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -79,17 +115,26 @@ export const handleSSE = async (url: string, data: any, onMessage?: (data: SSEMe
|
|||||||
},
|
},
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const { status } = response
|
export const handleSSE = async (url: string, data: any, onMessage?: (data: SSEMessage[]) => void, config = { headers: {} }) => {
|
||||||
|
try {
|
||||||
|
let token = cookieUtils.get('authToken');
|
||||||
|
let response = await makeSSERequest(url, data, token || '', config);
|
||||||
|
|
||||||
switch(status) {
|
switch (response.status) {
|
||||||
case 401:
|
case 401:
|
||||||
if (url?.includes('/public')) {
|
if (url?.includes('/public')) {
|
||||||
return message.warning(i18n.t('common.publicApiCannotRefreshToken'));
|
return message.warning(i18n.t('common.publicApiCannotRefreshToken'));
|
||||||
}
|
}
|
||||||
window.location.href = `/#/login`;
|
try {
|
||||||
|
const newToken = await refreshTokenForSSE();
|
||||||
|
response = await makeSSERequest(url, data, newToken, config);
|
||||||
|
} catch (refreshError) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
if (!response.body) throw new Error('No response body');
|
if (!response.body) throw new Error('No response body');
|
||||||
|
|
||||||
const reader = response.body.getReader();
|
const reader = response.body.getReader();
|
||||||
@@ -118,10 +163,8 @@ export const handleSSE = async (url: string, data: any, onMessage?: (data: SSEMe
|
|||||||
if (buffer.trim() && onMessage) {
|
if (buffer.trim() && onMessage) {
|
||||||
onMessage(parseSSEToJSON(buffer) ?? {});
|
onMessage(parseSSEToJSON(buffer) ?? {});
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Request failed:', error);
|
console.error('Request failed:', error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
Reference in New Issue
Block a user