mirror of
https://github.com/wassname/chatGPTBox.git
synced 2026-07-31 12:10:15 +08:00
improve fetchSSE (#532)
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
// https://www.npmjs.com/package/eventsource-parser/v/1.1.1
|
||||
|
||||
function createParser(onParse) {
|
||||
let isFirstChunk
|
||||
let bytes
|
||||
let buffer
|
||||
let startingPosition
|
||||
let startingFieldLength
|
||||
let eventId
|
||||
let eventName
|
||||
let data
|
||||
reset()
|
||||
return {
|
||||
feed,
|
||||
reset,
|
||||
}
|
||||
function reset() {
|
||||
isFirstChunk = true
|
||||
bytes = []
|
||||
buffer = ''
|
||||
startingPosition = 0
|
||||
startingFieldLength = -1
|
||||
eventId = void 0
|
||||
eventName = void 0
|
||||
data = ''
|
||||
}
|
||||
|
||||
function feed(chunk) {
|
||||
bytes = bytes.concat(Array.from(chunk))
|
||||
buffer = new TextDecoder().decode(new Uint8Array(bytes))
|
||||
if (isFirstChunk && hasBom(buffer)) {
|
||||
buffer = buffer.slice(BOM.length)
|
||||
}
|
||||
isFirstChunk = false
|
||||
const length = buffer.length
|
||||
let position = 0
|
||||
let discardTrailingNewline = false
|
||||
while (position < length) {
|
||||
if (discardTrailingNewline) {
|
||||
if (buffer[position] === '\n') {
|
||||
++position
|
||||
}
|
||||
discardTrailingNewline = false
|
||||
}
|
||||
let lineLength = -1
|
||||
let fieldLength = startingFieldLength
|
||||
let character
|
||||
for (let index = startingPosition; lineLength < 0 && index < length; ++index) {
|
||||
character = buffer[index]
|
||||
if (character === ':' && fieldLength < 0) {
|
||||
fieldLength = index - position
|
||||
} else if (character === '\r') {
|
||||
discardTrailingNewline = true
|
||||
lineLength = index - position
|
||||
} else if (character === '\n') {
|
||||
lineLength = index - position
|
||||
}
|
||||
}
|
||||
if (lineLength < 0) {
|
||||
startingPosition = length - position
|
||||
startingFieldLength = fieldLength
|
||||
break
|
||||
} else {
|
||||
startingPosition = 0
|
||||
startingFieldLength = -1
|
||||
}
|
||||
parseEventStreamLine(buffer, position, fieldLength, lineLength)
|
||||
position += lineLength + 1
|
||||
}
|
||||
if (position === length) {
|
||||
bytes = []
|
||||
buffer = ''
|
||||
} else if (position > 0) {
|
||||
bytes = bytes.slice(new TextEncoder().encode(buffer.slice(0, position)).length)
|
||||
buffer = buffer.slice(position)
|
||||
}
|
||||
}
|
||||
|
||||
function parseEventStreamLine(lineBuffer, index, fieldLength, lineLength) {
|
||||
if (lineLength === 0) {
|
||||
if (data.length > 0) {
|
||||
onParse({
|
||||
type: 'event',
|
||||
id: eventId,
|
||||
event: eventName || void 0,
|
||||
data: data.slice(0, -1),
|
||||
// remove trailing newline
|
||||
})
|
||||
|
||||
data = ''
|
||||
eventId = void 0
|
||||
}
|
||||
eventName = void 0
|
||||
return
|
||||
}
|
||||
const noValue = fieldLength < 0
|
||||
const field = lineBuffer.slice(index, index + (noValue ? lineLength : fieldLength))
|
||||
let step = 0
|
||||
if (noValue) {
|
||||
step = lineLength
|
||||
} else if (lineBuffer[index + fieldLength + 1] === ' ') {
|
||||
step = fieldLength + 2
|
||||
} else {
|
||||
step = fieldLength + 1
|
||||
}
|
||||
const position = index + step
|
||||
const valueLength = lineLength - step
|
||||
const value = lineBuffer.slice(position, position + valueLength).toString()
|
||||
if (field === 'data') {
|
||||
data += value ? ''.concat(value, '\n') : '\n'
|
||||
} else if (field === 'event') {
|
||||
eventName = value
|
||||
} else if (field === 'id' && !value.includes('\0')) {
|
||||
eventId = value
|
||||
} else if (field === 'retry') {
|
||||
const retry = parseInt(value, 10)
|
||||
if (!Number.isNaN(retry)) {
|
||||
onParse({
|
||||
type: 'reconnect-interval',
|
||||
value: retry,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const BOM = [239, 187, 191]
|
||||
function hasBom(buffer) {
|
||||
return BOM.every((charCode, index) => buffer.charCodeAt(index) === charCode)
|
||||
}
|
||||
export { createParser }
|
||||
Reference in New Issue
Block a user