From a8d585a378d8c086a7e2e784497d08778a24f242 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 27 Jun 2022 21:09:02 -0400 Subject: [PATCH] Revert "Undici (#5117)" This reverts commit 7ed3c95e0d0160f0b53469ec7c187ca528c0ed88. --- .changeset/slimy-ways-stare.md | 5 --- documentation/docs/01-web-standards.md | 4 -- packages/kit/package.json | 2 +- packages/kit/src/node/index.js | 39 ++++-------------- packages/kit/src/node/polyfills.js | 11 ++--- packages/kit/src/runtime/server/endpoint.js | 13 ++---- .../kit/src/runtime/server/page/load_node.js | 5 --- packages/kit/src/runtime/server/utils.js | 10 ++--- packages/kit/src/utils/http.spec.js | 4 +- .../index.svelte => large-response.svelte} | 4 +- .../routes/load/large-response/text.txt.js | 23 ----------- packages/kit/test/apps/basics/test/test.js | 41 ++++++++++++++++++- packages/kit/test/typings/endpoint.test.ts | 16 ++++---- packages/kit/types/index.d.ts | 2 +- pnpm-lock.yaml | 9 +--- 15 files changed, 71 insertions(+), 117 deletions(-) delete mode 100644 .changeset/slimy-ways-stare.md rename packages/kit/test/apps/basics/src/routes/load/{large-response/index.svelte => large-response.svelte} (64%) delete mode 100644 packages/kit/test/apps/basics/src/routes/load/large-response/text.txt.js diff --git a/.changeset/slimy-ways-stare.md b/.changeset/slimy-ways-stare.md deleted file mode 100644 index dcdab7f24b52..000000000000 --- a/.changeset/slimy-ways-stare.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@sveltejs/kit': patch ---- - -[breaking] use undici instead of node-fetch diff --git a/documentation/docs/01-web-standards.md b/documentation/docs/01-web-standards.md index 3caf22fae82b..ecf44be5eb81 100644 --- a/documentation/docs/01-web-standards.md +++ b/documentation/docs/01-web-standards.md @@ -45,10 +45,6 @@ export function get(event) { } ``` -### Stream APIs - -Most of the time, your endpoints will return complete data, as in the `userAgent` example above. Sometimes, you may need to return a response that's too large to fit in memory in one go, or is delivered in chunks, and for this the platform provides [streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) — [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream), [WritableStream](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) and [TransformStream](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream). - ### URL APIs URLs are represented by the [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) interface, which includes useful properties like `origin` and `pathname` (and, in the browser, `hash`). This interface shows up in various places — `event.url` in [hooks](/docs/hooks) and [endpoints](/docs/routing#endpoints), [`$page.url`](/docs/modules#$app-stores) in [pages](/docs/routing#pages), `from` and `to` in [`beforeNavigate` and `afterNavigate`](/docs/modules#$app-navigation) and so on. diff --git a/packages/kit/package.json b/packages/kit/package.json index cc72d674af55..90d489be8692 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -33,6 +33,7 @@ "locate-character": "^2.0.5", "marked": "^4.0.16", "mime": "^3.0.0", + "node-fetch": "^3.2.4", "port-authority": "^1.2.0", "rollup": "^2.75.3", "selfsigned": "^2.0.1", @@ -44,7 +45,6 @@ "svelte2tsx": "~0.5.10", "tiny-glob": "^0.2.9", "typescript": "^4.7.2", - "undici": "^5.4.0", "uvu": "^0.5.3" }, "peerDependencies": { diff --git a/packages/kit/src/node/index.js b/packages/kit/src/node/index.js index 1b30bd113389..1600e05bb71c 100644 --- a/packages/kit/src/node/index.js +++ b/packages/kit/src/node/index.js @@ -1,3 +1,4 @@ +import { Readable } from 'stream'; import * as set_cookie_parser from 'set-cookie-parser'; /** @param {import('http').IncomingMessage} req */ @@ -63,7 +64,6 @@ export async function getRequest(base, req) { delete headers[':authority']; delete headers[':scheme']; } - return new Request(base + req.url, { method: req.method, headers, @@ -85,38 +85,13 @@ export async function setResponse(res, response) { res.writeHead(response.status, headers); - if (response.body) { - let cancelled = false; - - const reader = response.body.getReader(); - - res.on('close', () => { - reader.cancel(); - cancelled = true; - }); - - const next = async () => { - const { done, value } = await reader.read(); - - if (cancelled) return; - - if (done) { - res.end(); - return; - } - - res.write(Buffer.from(value), (error) => { - if (error) { - console.error('Error writing stream', error); - res.end(); - } else { - next(); - } - }); - }; - - next(); + if (response.body instanceof Readable) { + response.body.pipe(res); } else { + if (response.body) { + res.write(new Uint8Array(await response.arrayBuffer())); + } + res.end(); } } diff --git a/packages/kit/src/node/polyfills.js b/packages/kit/src/node/polyfills.js index 66ae54b155d8..45502e66bedb 100644 --- a/packages/kit/src/node/polyfills.js +++ b/packages/kit/src/node/polyfills.js @@ -1,5 +1,4 @@ -import { fetch, Response, Request, Headers } from 'undici'; -import { ReadableStream, TransformStream, WritableStream } from 'stream/web'; +import fetch, { Response, Request, Headers } from 'node-fetch'; import { webcrypto as crypto } from 'crypto'; /** @type {Record} */ @@ -8,17 +7,13 @@ const globals = { fetch, Response, Request, - Headers, - ReadableStream, - TransformStream, - WritableStream + Headers }; // exported for dev/preview and node environments export function installPolyfills() { for (const name in globals) { - if (name in globalThis) continue; - + // TODO use built-in fetch once https://github.com/nodejs/undici/issues/1262 is resolved Object.defineProperty(globalThis, name, { enumerable: true, configurable: true, diff --git a/packages/kit/src/runtime/server/endpoint.js b/packages/kit/src/runtime/server/endpoint.js index 8ab8d2dd312a..739111b6d7c2 100644 --- a/packages/kit/src/runtime/server/endpoint.js +++ b/packages/kit/src/runtime/server/endpoint.js @@ -21,8 +21,6 @@ const text_types = new Set([ 'multipart/form-data' ]); -const bodyless_status_codes = new Set([101, 204, 205, 304]); - /** * Decides how the body should be parsed based on its mime type * @@ -126,11 +124,8 @@ export async function render_endpoint(event, mod) { } } - return new Response( - method !== 'head' && !bodyless_status_codes.has(status) ? normalized_body : undefined, - { - status, - headers - } - ); + return new Response(method !== 'head' ? normalized_body : undefined, { + status, + headers + }); } diff --git a/packages/kit/src/runtime/server/page/load_node.js b/packages/kit/src/runtime/server/page/load_node.js index 262d021c8ff3..f14bc75a6ba5 100644 --- a/packages/kit/src/runtime/server/page/load_node.js +++ b/packages/kit/src/runtime/server/page/load_node.js @@ -250,11 +250,6 @@ export async function load_node({ if (cookie) opts.headers.set('cookie', cookie); } - // we need to delete the connection header, as explained here: - // https://github.com/nodejs/undici/issues/1470#issuecomment-1140798467 - // TODO this may be a case for being selective about which headers we let through - opts.headers.delete('connection'); - const external_request = new Request(requested, /** @type {RequestInit} */ (opts)); response = await options.hooks.externalFetch.call(null, external_request); } diff --git a/packages/kit/src/runtime/server/utils.js b/packages/kit/src/runtime/server/utils.js index 6fddaa9009ae..e4e74b85ada9 100644 --- a/packages/kit/src/runtime/server/utils.js +++ b/packages/kit/src/runtime/server/utils.js @@ -39,13 +39,9 @@ export function is_pojo(body) { if (body) { if (body instanceof Uint8Array) return false; - // if body is a node Readable, throw an error - // TODO remove this for 1.0 - if (body._readableState && typeof body.pipe === 'function') { - throw new Error('Node streams are no longer supported — use a ReadableStream instead'); - } - - if (body instanceof ReadableStream) return false; + // body could be a node Readable, but we don't want to import + // node built-ins, so we use duck typing + if (body._readableState && typeof body.pipe === 'function') return false; // similarly, it could be a web ReadableStream if (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) return false; diff --git a/packages/kit/src/utils/http.spec.js b/packages/kit/src/utils/http.spec.js index e377a4140eaa..de6c88f180cd 100644 --- a/packages/kit/src/utils/http.spec.js +++ b/packages/kit/src/utils/http.spec.js @@ -1,9 +1,7 @@ import { test } from 'uvu'; import * as assert from 'uvu/assert'; import { to_headers } from './http.js'; -import { Headers } from 'undici'; - -// @ts-ignore +import { Headers } from 'node-fetch'; globalThis.Headers = Headers; test('handle header string value', () => { diff --git a/packages/kit/test/apps/basics/src/routes/load/large-response/index.svelte b/packages/kit/test/apps/basics/src/routes/load/large-response.svelte similarity index 64% rename from packages/kit/test/apps/basics/src/routes/load/large-response/index.svelte rename to packages/kit/test/apps/basics/src/routes/load/large-response.svelte index 20f6fff18c83..1ac6566d53d9 100644 --- a/packages/kit/test/apps/basics/src/routes/load/large-response/index.svelte +++ b/packages/kit/test/apps/basics/src/routes/load/large-response.svelte @@ -1,7 +1,7 @@