From 7d37fc90450b510fd291590e4432e9da91276472 Mon Sep 17 00:00:00 2001 From: itz_syruz Date: Sun, 16 Nov 2025 11:49:50 +0530 Subject: [PATCH 1/2] doc: document differences between Node.js fetch and WHATWG Fetch Standard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a new documentation section detailing intentional divergences between Node.js’s implementation of the Fetch API and the WHATWG Fetch Standard. This includes request-body streaming semantics, async iterable support, FormData Blob streaming, CORS behavior, header restrictions, redirect handling, resource management considerations, unsupported features, and implementation notes relating to undici. This consolidation improves clarity for developers and reduces repeated questions around Node.js fetch behavior. --- doc/api/globals.md | 97 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/doc/api/globals.md b/doc/api/globals.md index fee0236de5004c..2f7ecc16fb5402 100644 --- a/doc/api/globals.md +++ b/doc/api/globals.md @@ -579,6 +579,103 @@ The following globals are available to use with `fetch`: * [`Request`](https://nodejs.org/api/globals.html#request) * [`Response`](https://nodejs.org/api/globals.html#response). +### Differences from the WHATWG Fetch Standard + +Node.js implements the [WHATWG Fetch Standard][] with intentional differences to better support server-side JavaScript environments. + +#### Request Body Extensions + +##### Async iterable request bodies + +Node.js supports async iterables as request bodies—a behavior not included in the Fetch Standard. +```js +const data = { + async *[Symbol.asyncIterator]() { + yield 'hello'; + yield 'world'; + } +}; + +await fetch('https://example.com', { + method: 'POST', + body: data, + duplex: 'half' +}); +``` + +When using an async iterable or a `ReadableStream` as the request body, the `duplex` option must be set to `'half'`. + +##### FormData with stream-backed Blob objects + +`FormData` entries may include stream-backed `Blob` objects created from the filesystem, enabling efficient uploads of large files without buffering them in memory. +```js +import { openAsBlob } from 'node:fs'; + +const file = await openAsBlob('./large-file.csv'); +const form = new FormData(); +form.set('file', file, 'large-file.csv'); + +await fetch('https://example.com', { method: 'POST', body: form }); +``` + +#### Response Body Extensions + +##### Async iterable response bodies + +The `Response` constructor accepts async iterables, allowing flexible construction of streaming responses in server environments. +```js +const res = new Response(asyncIterable); +``` + +#### CORS Behavior + +Node.js does not implement CORS enforcement. No preflight requests are issued, and CORS response headers are not validated. All cross-origin requests are permitted. + +Applications requiring origin-based access control must implement these checks manually. + +#### Header Restrictions + +The Fetch Standard restricts certain headers for browser security reasons. Node.js removes these restrictions, allowing all headers—including `Host`, `Connection`, and `Content-Length`—to be set programmatically. + +#### Redirect Handling + +When using `redirect: 'manual'`, Node.js returns the actual redirect response rather than an opaque filtered response. This matches other server-side runtimes and allows inspection of redirect details. + +#### Resource Management and Garbage Collection + +In Node.js, unconsumed response bodies may delay the release of underlying network resources. This can reduce connection reuse or cause stalls under load. + +Always consume or cancel the response body: +```js +const res = await fetch(url); +for await (const chunk of res.body) { + // process chunk +} +``` + +For header-only requests, prefer `HEAD` to avoid creating a body: +```js +const headers = (await fetch(url, { method: 'HEAD' })).headers; +``` + +#### Unsupported Features + +##### `Expect: 100-continue` + +The `Expect` request header is not supported. Request bodies are sent immediately, and `100 Continue` responses are ignored. + +#### Implementation Notes + +Node.js uses the [undici][] HTTP client internally to implement `fetch()`. The bundled version can be inspected with: +```js +console.log(process.versions.undici); +``` + +For additional features—such as advanced agents, interceptors, or custom connection pooling—install `undici` as a separate dependency. + +[WHATWG Fetch Standard]: https://fetch.spec.whatwg.org/ +[undici]: https://undici.nodejs.org/ + ## Class: `File`