@ricsam/isolate-fetch 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -0
- package/dist/cjs/index.cjs +1800 -0
- package/dist/cjs/index.cjs.map +10 -0
- package/dist/cjs/package.json +5 -0
- package/dist/cjs/stream-state.cjs +230 -0
- package/dist/cjs/stream-state.cjs.map +10 -0
- package/{src/index.ts → dist/mjs/index.mjs} +357 -923
- package/dist/mjs/index.mjs.map +10 -0
- package/dist/mjs/package.json +5 -0
- package/dist/mjs/stream-state.mjs +199 -0
- package/dist/mjs/stream-state.mjs.map +10 -0
- package/dist/types/index.d.ts +63 -0
- package/dist/types/isolate.d.ts +267 -0
- package/dist/types/stream-state.d.ts +61 -0
- package/package.json +41 -13
- package/CHANGELOG.md +0 -9
- package/src/debug-delayed.test.ts +0 -89
- package/src/debug-streaming.test.ts +0 -81
- package/src/download-streaming-simple.test.ts +0 -167
- package/src/download-streaming.test.ts +0 -286
- package/src/form-data.test.ts +0 -824
- package/src/formdata.test.ts +0 -212
- package/src/headers.test.ts +0 -582
- package/src/host-backed-stream.test.ts +0 -363
- package/src/index.test.ts +0 -274
- package/src/integration.test.ts +0 -665
- package/src/request.test.ts +0 -482
- package/src/response.test.ts +0 -520
- package/src/serve.test.ts +0 -425
- package/src/stream-state.test.ts +0 -338
- package/src/stream-state.ts +0 -337
- package/src/upload-streaming.test.ts +0 -373
- package/src/websocket.test.ts +0 -627
- package/tsconfig.json +0 -8
package/src/serve.test.ts
DELETED
|
@@ -1,425 +0,0 @@
|
|
|
1
|
-
import { test, describe, beforeEach, afterEach } from "node:test";
|
|
2
|
-
import assert from "node:assert";
|
|
3
|
-
import ivm from "isolated-vm";
|
|
4
|
-
import { setupFetch, clearAllInstanceState, type FetchHandle } from "./index.ts";
|
|
5
|
-
|
|
6
|
-
describe("serve()", () => {
|
|
7
|
-
let isolate: ivm.Isolate;
|
|
8
|
-
let context: ivm.Context;
|
|
9
|
-
let fetchHandle: FetchHandle;
|
|
10
|
-
|
|
11
|
-
beforeEach(async () => {
|
|
12
|
-
isolate = new ivm.Isolate();
|
|
13
|
-
context = await isolate.createContext();
|
|
14
|
-
clearAllInstanceState();
|
|
15
|
-
fetchHandle = await setupFetch(context);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
afterEach(() => {
|
|
19
|
-
fetchHandle.dispose();
|
|
20
|
-
context.release();
|
|
21
|
-
isolate.dispose();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test("serve() returns response with body", async () => {
|
|
25
|
-
context.evalSync(`
|
|
26
|
-
serve({
|
|
27
|
-
fetch(request, server) {
|
|
28
|
-
return new Response("Hello!");
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
`);
|
|
32
|
-
|
|
33
|
-
const response = await fetchHandle.dispatchRequest(
|
|
34
|
-
new Request("http://localhost/test")
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
assert.strictEqual(response.status, 200);
|
|
38
|
-
assert.strictEqual(await response.text(), "Hello!");
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test("serve() returns JSON response", async () => {
|
|
42
|
-
context.evalSync(`
|
|
43
|
-
serve({
|
|
44
|
-
fetch(request, server) {
|
|
45
|
-
return Response.json({ message: "Hello, World!" });
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
`);
|
|
49
|
-
|
|
50
|
-
const response = await fetchHandle.dispatchRequest(
|
|
51
|
-
new Request("http://localhost/test")
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
assert.strictEqual(response.status, 200);
|
|
55
|
-
assert.strictEqual(response.headers.get("content-type"), "application/json");
|
|
56
|
-
const data = await response.json();
|
|
57
|
-
assert.deepStrictEqual(data, { message: "Hello, World!" });
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("serve() handles request properties", async () => {
|
|
61
|
-
context.evalSync(`
|
|
62
|
-
serve({
|
|
63
|
-
fetch(request, server) {
|
|
64
|
-
const url = request.url;
|
|
65
|
-
const method = request.method;
|
|
66
|
-
return new Response("URL: " + url + ", Method: " + method);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
`);
|
|
70
|
-
|
|
71
|
-
const response = await fetchHandle.dispatchRequest(
|
|
72
|
-
new Request("http://localhost/test", { method: "POST" })
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
assert.strictEqual(response.status, 200);
|
|
76
|
-
assert.strictEqual(await response.text(), "URL: http://localhost/test, Method: POST");
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("serve() with async fetch handler", async () => {
|
|
80
|
-
context.evalSync(`
|
|
81
|
-
serve({
|
|
82
|
-
async fetch(request, server) {
|
|
83
|
-
return Response.json({ message: "Hello from isolate!" });
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
`);
|
|
87
|
-
|
|
88
|
-
const response = await fetchHandle.dispatchRequest(
|
|
89
|
-
new Request("http://localhost/test")
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
assert.strictEqual(response.status, 200);
|
|
93
|
-
assert.strictEqual(response.headers.get("content-type"), "application/json");
|
|
94
|
-
const data = await response.json();
|
|
95
|
-
assert.deepStrictEqual(data, { message: "Hello from isolate!" });
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test("serve() with Headers(undefined) should return valid response", async () => {
|
|
99
|
-
context.evalSync(`
|
|
100
|
-
serve({
|
|
101
|
-
fetch(request, server) {
|
|
102
|
-
const responseHeaders = new Headers(undefined);
|
|
103
|
-
return new Response(JSON.stringify([]), {
|
|
104
|
-
status: 200,
|
|
105
|
-
headers: responseHeaders,
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
`);
|
|
110
|
-
|
|
111
|
-
const response = await fetchHandle.dispatchRequest(
|
|
112
|
-
new Request("http://localhost/test")
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
assert.strictEqual(response.status, 200);
|
|
116
|
-
const data = await response.json();
|
|
117
|
-
assert.deepStrictEqual(data, []);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test("serve() with Headers instance passed to Response", async () => {
|
|
121
|
-
context.evalSync(`
|
|
122
|
-
serve({
|
|
123
|
-
fetch(request, server) {
|
|
124
|
-
const headers = new Headers({ "Content-Type": "application/json" });
|
|
125
|
-
return new Response(JSON.stringify({ ok: true }), {
|
|
126
|
-
status: 200,
|
|
127
|
-
headers: headers,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
`);
|
|
132
|
-
|
|
133
|
-
const response = await fetchHandle.dispatchRequest(
|
|
134
|
-
new Request("http://localhost/test")
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
assert.strictEqual(response.status, 200);
|
|
138
|
-
assert.strictEqual(response.headers.get("content-type"), "application/json");
|
|
139
|
-
const data = await response.json();
|
|
140
|
-
assert.deepStrictEqual(data, { ok: true });
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
test("Response should have same attributes as native Response - basic", async () => {
|
|
144
|
-
context.evalSync(`
|
|
145
|
-
serve({
|
|
146
|
-
fetch(request) {
|
|
147
|
-
return new Response("Hello, world!", { status: 200 });
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
`);
|
|
151
|
-
|
|
152
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
153
|
-
new Request("http://localhost/test")
|
|
154
|
-
);
|
|
155
|
-
const nativeResponse = new Response("Hello, world!", { status: 200 });
|
|
156
|
-
|
|
157
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
158
|
-
assert.strictEqual(isolateResponse.statusText, nativeResponse.statusText);
|
|
159
|
-
assert.strictEqual(isolateResponse.ok, nativeResponse.ok);
|
|
160
|
-
assert.strictEqual(await isolateResponse.text(), await nativeResponse.text());
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
test("Response should have same attributes as native Response - with statusText", async () => {
|
|
164
|
-
context.evalSync(`
|
|
165
|
-
serve({
|
|
166
|
-
fetch(request) {
|
|
167
|
-
return new Response("Created!", { status: 201, statusText: "Created" });
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
`);
|
|
171
|
-
|
|
172
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
173
|
-
new Request("http://localhost/test")
|
|
174
|
-
);
|
|
175
|
-
const nativeResponse = new Response("Created!", { status: 201, statusText: "Created" });
|
|
176
|
-
|
|
177
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
178
|
-
assert.strictEqual(isolateResponse.statusText, nativeResponse.statusText);
|
|
179
|
-
assert.strictEqual(isolateResponse.ok, nativeResponse.ok);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
test("Response should have same attributes as native Response - error status", async () => {
|
|
183
|
-
context.evalSync(`
|
|
184
|
-
serve({
|
|
185
|
-
fetch(request) {
|
|
186
|
-
return new Response("Not Found", { status: 404, statusText: "Not Found" });
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
`);
|
|
190
|
-
|
|
191
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
192
|
-
new Request("http://localhost/test")
|
|
193
|
-
);
|
|
194
|
-
const nativeResponse = new Response("Not Found", { status: 404, statusText: "Not Found" });
|
|
195
|
-
|
|
196
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
197
|
-
assert.strictEqual(isolateResponse.statusText, nativeResponse.statusText);
|
|
198
|
-
assert.strictEqual(isolateResponse.ok, nativeResponse.ok);
|
|
199
|
-
assert.strictEqual(isolateResponse.ok, false);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
test("Response should have same attributes as native Response - with headers object", async () => {
|
|
203
|
-
context.evalSync(`
|
|
204
|
-
serve({
|
|
205
|
-
fetch(request) {
|
|
206
|
-
return new Response("test", {
|
|
207
|
-
status: 200,
|
|
208
|
-
headers: {
|
|
209
|
-
"Content-Type": "text/plain",
|
|
210
|
-
"X-Custom-Header": "custom-value"
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
`);
|
|
216
|
-
|
|
217
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
218
|
-
new Request("http://localhost/test")
|
|
219
|
-
);
|
|
220
|
-
const nativeResponse = new Response("test", {
|
|
221
|
-
status: 200,
|
|
222
|
-
headers: {
|
|
223
|
-
"Content-Type": "text/plain",
|
|
224
|
-
"X-Custom-Header": "custom-value"
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
assert.strictEqual(isolateResponse.headers.get("content-type"), nativeResponse.headers.get("content-type"));
|
|
229
|
-
assert.strictEqual(isolateResponse.headers.get("x-custom-header"), nativeResponse.headers.get("x-custom-header"));
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test("Response should have same attributes as native Response - with Headers instance", async () => {
|
|
233
|
-
context.evalSync(`
|
|
234
|
-
serve({
|
|
235
|
-
fetch(request) {
|
|
236
|
-
const headers = new Headers();
|
|
237
|
-
headers.set("Content-Type", "application/json");
|
|
238
|
-
headers.set("X-Request-Id", "12345");
|
|
239
|
-
return new Response('{"data": true}', { status: 200, headers });
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
`);
|
|
243
|
-
|
|
244
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
245
|
-
new Request("http://localhost/test")
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
const nativeHeaders = new Headers();
|
|
249
|
-
nativeHeaders.set("Content-Type", "application/json");
|
|
250
|
-
nativeHeaders.set("X-Request-Id", "12345");
|
|
251
|
-
const nativeResponse = new Response('{"data": true}', { status: 200, headers: nativeHeaders });
|
|
252
|
-
|
|
253
|
-
assert.strictEqual(isolateResponse.headers.get("content-type"), nativeResponse.headers.get("content-type"));
|
|
254
|
-
assert.strictEqual(isolateResponse.headers.get("x-request-id"), nativeResponse.headers.get("x-request-id"));
|
|
255
|
-
assert.deepStrictEqual(await isolateResponse.json(), await nativeResponse.json());
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
test("Response.json() should have same attributes as native Response.json()", async () => {
|
|
259
|
-
context.evalSync(`
|
|
260
|
-
serve({
|
|
261
|
-
fetch(request) {
|
|
262
|
-
return Response.json({ message: "hello", count: 42 });
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
`);
|
|
266
|
-
|
|
267
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
268
|
-
new Request("http://localhost/test")
|
|
269
|
-
);
|
|
270
|
-
const nativeResponse = Response.json({ message: "hello", count: 42 });
|
|
271
|
-
|
|
272
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
273
|
-
assert.ok(isolateResponse.headers.get("content-type")?.includes("application/json"));
|
|
274
|
-
assert.ok(nativeResponse.headers.get("content-type")?.includes("application/json"));
|
|
275
|
-
assert.deepStrictEqual(await isolateResponse.json(), await nativeResponse.json());
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
test("Response.json() with custom status should match native", async () => {
|
|
279
|
-
context.evalSync(`
|
|
280
|
-
serve({
|
|
281
|
-
fetch(request) {
|
|
282
|
-
return Response.json({ error: "not found" }, { status: 404 });
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
`);
|
|
286
|
-
|
|
287
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
288
|
-
new Request("http://localhost/test")
|
|
289
|
-
);
|
|
290
|
-
const nativeResponse = Response.json({ error: "not found" }, { status: 404 });
|
|
291
|
-
|
|
292
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
293
|
-
assert.strictEqual(isolateResponse.ok, nativeResponse.ok);
|
|
294
|
-
assert.deepStrictEqual(await isolateResponse.json(), await nativeResponse.json());
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
test("Response.redirect() should have same attributes as native Response.redirect()", async () => {
|
|
298
|
-
context.evalSync(`
|
|
299
|
-
serve({
|
|
300
|
-
fetch(request) {
|
|
301
|
-
return Response.redirect("https://example.com/new-location");
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
`);
|
|
305
|
-
|
|
306
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
307
|
-
new Request("http://localhost/test")
|
|
308
|
-
);
|
|
309
|
-
const nativeResponse = Response.redirect("https://example.com/new-location");
|
|
310
|
-
|
|
311
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
312
|
-
assert.strictEqual(isolateResponse.headers.get("location"), nativeResponse.headers.get("location"));
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
test("Response.redirect() with custom status should match native", async () => {
|
|
316
|
-
context.evalSync(`
|
|
317
|
-
serve({
|
|
318
|
-
fetch(request) {
|
|
319
|
-
return Response.redirect("https://example.com/moved", 301);
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
`);
|
|
323
|
-
|
|
324
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
325
|
-
new Request("http://localhost/test")
|
|
326
|
-
);
|
|
327
|
-
const nativeResponse = Response.redirect("https://example.com/moved", 301);
|
|
328
|
-
|
|
329
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
330
|
-
assert.strictEqual(isolateResponse.headers.get("location"), nativeResponse.headers.get("location"));
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
test("Response with null body should match native", async () => {
|
|
334
|
-
context.evalSync(`
|
|
335
|
-
serve({
|
|
336
|
-
fetch(request) {
|
|
337
|
-
return new Response(null, { status: 204 });
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
`);
|
|
341
|
-
|
|
342
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
343
|
-
new Request("http://localhost/test")
|
|
344
|
-
);
|
|
345
|
-
const nativeResponse = new Response(null, { status: 204 });
|
|
346
|
-
|
|
347
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
348
|
-
assert.strictEqual(await isolateResponse.text(), await nativeResponse.text());
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
test("Response with ArrayBuffer body should match native", async () => {
|
|
352
|
-
context.evalSync(`
|
|
353
|
-
serve({
|
|
354
|
-
fetch(request) {
|
|
355
|
-
const buffer = new Uint8Array([72, 101, 108, 108, 111]).buffer;
|
|
356
|
-
return new Response(buffer, {
|
|
357
|
-
status: 200,
|
|
358
|
-
headers: { "Content-Type": "application/octet-stream" }
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
`);
|
|
363
|
-
|
|
364
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
365
|
-
new Request("http://localhost/test")
|
|
366
|
-
);
|
|
367
|
-
|
|
368
|
-
const buffer = new Uint8Array([72, 101, 108, 108, 111]).buffer;
|
|
369
|
-
const nativeResponse = new Response(buffer, {
|
|
370
|
-
status: 200,
|
|
371
|
-
headers: { "Content-Type": "application/octet-stream" }
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
375
|
-
assert.strictEqual(isolateResponse.headers.get("content-type"), nativeResponse.headers.get("content-type"));
|
|
376
|
-
|
|
377
|
-
const isolateBuffer = await isolateResponse.arrayBuffer();
|
|
378
|
-
const nativeBuffer = await nativeResponse.arrayBuffer();
|
|
379
|
-
assert.deepStrictEqual(new Uint8Array(isolateBuffer), new Uint8Array(nativeBuffer));
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
test("Response with Uint8Array body should match native", async () => {
|
|
383
|
-
context.evalSync(`
|
|
384
|
-
serve({
|
|
385
|
-
fetch(request) {
|
|
386
|
-
const bytes = new Uint8Array([87, 111, 114, 108, 100]);
|
|
387
|
-
return new Response(bytes, { status: 200 });
|
|
388
|
-
}
|
|
389
|
-
});
|
|
390
|
-
`);
|
|
391
|
-
|
|
392
|
-
const isolateResponse = await fetchHandle.dispatchRequest(
|
|
393
|
-
new Request("http://localhost/test")
|
|
394
|
-
);
|
|
395
|
-
|
|
396
|
-
const bytes = new Uint8Array([87, 111, 114, 108, 100]);
|
|
397
|
-
const nativeResponse = new Response(bytes, { status: 200 });
|
|
398
|
-
|
|
399
|
-
assert.strictEqual(isolateResponse.status, nativeResponse.status);
|
|
400
|
-
assert.strictEqual(await isolateResponse.text(), await nativeResponse.text());
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
test("hasServeHandler returns true after serve() is called", async () => {
|
|
404
|
-
assert.strictEqual(fetchHandle.hasServeHandler(), false);
|
|
405
|
-
|
|
406
|
-
context.evalSync(`
|
|
407
|
-
serve({
|
|
408
|
-
fetch(request) {
|
|
409
|
-
return new Response("OK");
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
`);
|
|
413
|
-
|
|
414
|
-
assert.strictEqual(fetchHandle.hasServeHandler(), true);
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
test("dispatchRequest throws if no serve handler", async () => {
|
|
418
|
-
await assert.rejects(
|
|
419
|
-
async () => {
|
|
420
|
-
await fetchHandle.dispatchRequest(new Request("http://localhost/test"));
|
|
421
|
-
},
|
|
422
|
-
/No serve\(\) handler registered/
|
|
423
|
-
);
|
|
424
|
-
});
|
|
425
|
-
});
|