Skip to content

Commit 564608d

Browse files
committed
chore: ♻️ lift changes from #5694 to fetch package so I can build on top of them
1 parent a7b0ff9 commit 564608d

File tree

2 files changed

+48
-27
lines changed

2 files changed

+48
-27
lines changed

packages/fetch/src/fetch.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,19 +107,30 @@ export async function fetchwithRequestOptions(
107107
}
108108

109109
// fetch the request with the provided options
110-
const resp = await fetch(url, {
111-
...init,
112-
body: updatedBody ?? init?.body,
113-
headers: headers,
114-
agent: agent,
115-
});
116-
117-
if (!resp.ok) {
118-
const requestId = resp.headers.get("x-request-id");
119-
if (requestId) {
120-
console.log(`Request ID: ${requestId}, Status: ${resp.status}`);
110+
try {
111+
const resp = await fetch(url, {
112+
...init,
113+
body: updatedBody ?? init?.body,
114+
headers: headers,
115+
agent: agent,
116+
});
117+
118+
if (!resp.ok) {
119+
const requestId = resp.headers.get("x-request-id");
120+
if (requestId) {
121+
console.log(`Request ID: ${requestId}, Status: ${resp.status}`);
122+
}
121123
}
122-
}
123124

124-
return resp;
125+
return resp;
126+
} catch (error) {
127+
if (error instanceof Error && error.name === "AbortError") {
128+
// Return a Response object that streamResponse etc can handle
129+
return new Response(null, {
130+
status: 499, // Client Closed Request
131+
statusText: "Client Closed Request",
132+
});
133+
}
134+
throw error;
135+
}
125136
}

packages/fetch/src/stream.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export async function* toAsyncIterable(
1010
export async function* streamResponse(
1111
response: Response,
1212
): AsyncGenerator<string> {
13+
if (response.status === 499) {
14+
return; // In case of client-side cancellation, just return
15+
}
1316
if (response.status !== 200) {
1417
throw new Error(await response.text());
1518
}
@@ -21,22 +24,29 @@ export async function* streamResponse(
2124
// Get the major version of Node.js
2225
const nodeMajorVersion = parseInt(process.versions.node.split(".")[0], 10);
2326

24-
if (nodeMajorVersion >= 20) {
25-
// Use the new API for Node 20 and above
26-
const stream = (ReadableStream as any).from(response.body);
27-
for await (const chunk of stream.pipeThrough(
28-
new TextDecoderStream("utf-8"),
29-
)) {
30-
yield chunk;
27+
try {
28+
if (nodeMajorVersion >= 20) {
29+
// Use the new API for Node 20 and above
30+
const stream = (ReadableStream as any).from(response.body);
31+
for await (const chunk of stream.pipeThrough(
32+
new TextDecoderStream("utf-8"),
33+
)) {
34+
yield chunk;
35+
}
36+
} else {
37+
// Fallback for Node versions below 20
38+
// Streaming with this method doesn't work as version 20+ does
39+
const decoder = new TextDecoder("utf-8");
40+
const nodeStream = response.body as unknown as NodeJS.ReadableStream;
41+
for await (const chunk of toAsyncIterable(nodeStream)) {
42+
yield decoder.decode(chunk, { stream: true });
43+
}
3144
}
32-
} else {
33-
// Fallback for Node versions below 20
34-
// Streaming with this method doesn't work as version 20+ does
35-
const decoder = new TextDecoder("utf-8");
36-
const nodeStream = response.body as unknown as NodeJS.ReadableStream;
37-
for await (const chunk of toAsyncIterable(nodeStream)) {
38-
yield decoder.decode(chunk, { stream: true });
45+
} catch (e) {
46+
if (e instanceof Error && e.name.startsWith("AbortError")) {
47+
return; // In case of client-side cancellation, just return
3948
}
49+
throw e;
4050
}
4151
}
4252

0 commit comments

Comments
 (0)