forked from easychen/api2d-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfetchSSE.js
78 lines (65 loc) · 2.18 KB
/
fetchSSE.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
const { createParser } = require('eventsource-parser');
module.exports = async function fetchSSE(url, options, fetch) {
const { onmessage, onError, ...fetchOptions } = options;
const res = await fetch(url, fetchOptions);
if (!res.ok) {
let reason;
try {
reason = await res.text();
} catch (err) {
reason = res.statusText;
}
const msg = `ChatGPT error ${res.status}: ${reason}`;
const error = new Error(msg, { cause: res });
error.statusCode = res.status;
error.statusText = res.statusText;
throw error;
}
const parser = createParser((event) => {
if (event.type === 'event') {
onmessage(event.data);
}
});
// handle special response errors
const feed = (chunk) => {
let response = null;
try {
response = JSON.parse(chunk);
} catch {
// ignore
}
if (response?.detail?.type === 'invalid_request_error') {
const msg = `ChatGPT error ${response.detail.message}: ${response.detail.code} (${response.detail.type})`;
const error = new Error(msg, { cause: response });
error.statusCode = response.detail.code;
error.statusText = response.detail.message;
if (onError) {
onError(error);
} else {
console.error(error);
}
// don't feed to the event parser
return;
}
parser.feed(chunk);
};
if (!res.body.getReader) {
// Vercel polyfills `fetch` with `node-fetch`, which doesn't conform to
// web standards, so this is a workaround...
const body = res.body;
if (!body.on || !body.read) {
throw new Error('unsupported "fetch" implementation');
}
body.on('readable', () => {
let chunk;
while (null !== (chunk = body.read())) {
feed(chunk.toString());
}
});
} else {
for await (const chunk of streamAsyncIterable(res.body)) {
const str = new TextDecoder().decode(chunk);
feed(str);
}
}
};