feat: fetch stream compatibility enhance (#1551)

This commit is contained in:
Ricky 2023-11-20 15:30:32 +08:00 committed by GitHub
parent 31195975f5
commit 657334a5fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 2 deletions

5
web/global.d.ts vendored
View File

@ -1,2 +1,5 @@
declare module 'lamejs';
declare module 'react-18-input-autosize';
declare module 'react-18-input-autosize';
declare module 'fetch-readablestream' {
export default function fetchReadableStream(url: string, options?: RequestInit): Promise<Response>
}

View File

@ -36,6 +36,7 @@
"echarts": "^5.4.1",
"echarts-for-react": "^3.0.2",
"emoji-mart": "^5.5.2",
"fetch-readablestream": "^0.2.0",
"i18next": "^22.4.13",
"i18next-resources-to-backend": "^1.1.3",
"immer": "^9.0.19",

View File

@ -1,8 +1,11 @@
import fetchStream from 'fetch-readablestream'
import { API_PREFIX, IS_CE_EDITION, PUBLIC_API_PREFIX } from '@/config'
import Toast from '@/app/components/base/toast'
import type { MessageEnd, MessageReplace, ThoughtItem } from '@/app/components/app/chat/type'
import { isSupportNativeFetchStream } from '@/utils/stream'
const TIME_OUT = 100000
const supportNativeFetchStream = isSupportNativeFetchStream()
const ContentType = {
json: 'application/json',
@ -220,6 +223,9 @@ const baseFetch = <T>(
if (body && bodyStringify)
options.body = JSON.stringify(body)
// for those do not support native fetch stream, we use fetch-readablestream as polyfill
const doFetch = supportNativeFetchStream ? globalThis.fetch : fetchStream
// Handle timeout
return Promise.race([
new Promise((resolve, reject) => {
@ -228,7 +234,7 @@ const baseFetch = <T>(
}, TIME_OUT)
}),
new Promise((resolve, reject) => {
globalThis.fetch(urlWithPrefix, options as RequestInit)
doFetch(urlWithPrefix, options as RequestInit)
.then((res) => {
const resClone = res.clone()
// Error handler

21
web/utils/stream.ts Normal file
View File

@ -0,0 +1,21 @@
// https://developer.chrome.com/articles/fetch-streaming-requests/#feature-detection
export const isSupportNativeFetchStream = () => {
const supportsRequestStreams = (() => {
let duplexAccessed = false
const params = {
body: new ReadableStream(),
method: 'POST',
get duplex() {
duplexAccessed = true
return 'half'
},
}
const hasContentType = new Request('', params).headers.has('Content-Type')
return duplexAccessed && !hasContentType
})()
return supportsRequestStreams
}