refactor the logic of refreshing access_token (#10068)

This commit is contained in:
NFish
2024-11-05 12:38:31 +08:00
committed by GitHub
parent de5dfd99f6
commit 302f4407f6
7 changed files with 171 additions and 185 deletions

View File

@@ -1,3 +1,4 @@
import { refreshAccessTokenOrRelogin } from './refresh-token'
import { API_PREFIX, IS_CE_EDITION, PUBLIC_API_PREFIX } from '@/config'
import Toast from '@/app/components/base/toast'
import type { AnnotationReply, MessageEnd, MessageReplace, ThoughtItem } from '@/app/components/base/chat/chat/type'
@@ -356,39 +357,8 @@ const baseFetch = <T>(
if (!/^(2|3)\d{2}$/.test(String(res.status))) {
const bodyJson = res.json()
switch (res.status) {
case 401: {
if (isPublicAPI) {
return bodyJson.then((data: ResponseError) => {
if (data.code === 'web_sso_auth_required')
requiredWebSSOLogin()
if (data.code === 'unauthorized') {
removeAccessToken()
globalThis.location.reload()
}
return Promise.reject(data)
})
}
const loginUrl = `${globalThis.location.origin}/signin`
bodyJson.then((data: ResponseError) => {
if (data.code === 'init_validate_failed' && IS_CE_EDITION && !silent)
Toast.notify({ type: 'error', message: data.message, duration: 4000 })
else if (data.code === 'not_init_validated' && IS_CE_EDITION)
globalThis.location.href = `${globalThis.location.origin}/init`
else if (data.code === 'not_setup' && IS_CE_EDITION)
globalThis.location.href = `${globalThis.location.origin}/install`
else if (location.pathname !== '/signin' || !IS_CE_EDITION)
globalThis.location.href = loginUrl
else if (!silent)
Toast.notify({ type: 'error', message: data.message })
}).catch(() => {
// Handle any other errors
globalThis.location.href = loginUrl
})
break
}
case 401:
return Promise.reject(resClone)
case 403:
bodyJson.then((data: ResponseError) => {
if (!silent)
@@ -484,7 +454,9 @@ export const upload = (options: any, isPublicAPI?: boolean, url?: string, search
export const ssePost = (
url: string,
fetchOptions: FetchOptionType,
{
otherOptions: IOtherOptions,
) => {
const {
isPublicAPI = false,
onData,
onCompleted,
@@ -507,8 +479,7 @@ export const ssePost = (
onTextReplace,
onError,
getAbortController,
}: IOtherOptions,
) => {
} = otherOptions
const abortController = new AbortController()
const options = Object.assign({}, baseOptions, {
@@ -532,21 +503,29 @@ export const ssePost = (
globalThis.fetch(urlWithPrefix, options as RequestInit)
.then((res) => {
if (!/^(2|3)\d{2}$/.test(String(res.status))) {
res.json().then((data: any) => {
if (isPublicAPI) {
if (data.code === 'web_sso_auth_required')
requiredWebSSOLogin()
if (res.status === 401) {
refreshAccessTokenOrRelogin(TIME_OUT).then(() => {
ssePost(url, fetchOptions, otherOptions)
}).catch(() => {
res.json().then((data: any) => {
if (isPublicAPI) {
if (data.code === 'web_sso_auth_required')
requiredWebSSOLogin()
if (data.code === 'unauthorized') {
removeAccessToken()
globalThis.location.reload()
}
if (res.status === 401)
return
}
Toast.notify({ type: 'error', message: data.message || 'Server Error' })
})
onError?.('Server Error')
if (data.code === 'unauthorized') {
removeAccessToken()
globalThis.location.reload()
}
}
})
})
}
else {
res.json().then((data) => {
Toast.notify({ type: 'error', message: data.message || 'Server Error' })
})
onError?.('Server Error')
}
return
}
return handleStream(res, (str: string, isFirstMessage: boolean, moreInfo: IOnDataMoreInfo) => {
@@ -568,7 +547,54 @@ export const ssePost = (
// base request
export const request = <T>(url: string, options = {}, otherOptions?: IOtherOptions) => {
return baseFetch<T>(url, options, otherOptions || {})
return new Promise<T>((resolve, reject) => {
const otherOptionsForBaseFetch = otherOptions || {}
baseFetch<T>(url, options, otherOptionsForBaseFetch).then(resolve).catch((errResp) => {
if (errResp?.status === 401) {
return refreshAccessTokenOrRelogin(TIME_OUT).then(() => {
baseFetch<T>(url, options, otherOptionsForBaseFetch).then(resolve).catch(reject)
}).catch(() => {
const {
isPublicAPI = false,
silent,
} = otherOptionsForBaseFetch
const bodyJson = errResp.json()
if (isPublicAPI) {
return bodyJson.then((data: ResponseError) => {
if (data.code === 'web_sso_auth_required')
requiredWebSSOLogin()
if (data.code === 'unauthorized') {
removeAccessToken()
globalThis.location.reload()
}
return Promise.reject(data)
})
}
const loginUrl = `${globalThis.location.origin}/signin`
bodyJson.then((data: ResponseError) => {
if (data.code === 'init_validate_failed' && IS_CE_EDITION && !silent)
Toast.notify({ type: 'error', message: data.message, duration: 4000 })
else if (data.code === 'not_init_validated' && IS_CE_EDITION)
globalThis.location.href = `${globalThis.location.origin}/init`
else if (data.code === 'not_setup' && IS_CE_EDITION)
globalThis.location.href = `${globalThis.location.origin}/install`
else if (location.pathname !== '/signin' || !IS_CE_EDITION)
globalThis.location.href = loginUrl
else if (!silent)
Toast.notify({ type: 'error', message: data.message })
}).catch(() => {
// Handle any other errors
globalThis.location.href = loginUrl
})
})
}
else {
reject(errResp)
}
})
})
}
// request methods