Skip to content

Commit a950235

Browse files
doc: document differences between Node.js fetch and WHATWG Fetch Standard
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.
1 parent 1ce22dd commit a950235

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

doc/api/globals.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,103 @@ The following globals are available to use with `fetch`:
579579
* [`Request`](https://nodejs.org/api/globals.html#request)
580580
* [`Response`](https://nodejs.org/api/globals.html#response).
581581

582+
### Differences from the WHATWG Fetch Standard
583+
584+
Node.js implements the [WHATWG Fetch Standard][] with intentional differences to better support server-side JavaScript environments.
585+
586+
#### Request Body Extensions
587+
588+
##### Async iterable request bodies
589+
590+
Node.js supports async iterables as request bodies—a behavior not included in the Fetch Standard.
591+
```js
592+
const data = {
593+
async *[Symbol.asyncIterator]() {
594+
yield 'hello';
595+
yield 'world';
596+
}
597+
};
598+
599+
await fetch('https://example.com', {
600+
method: 'POST',
601+
body: data,
602+
duplex: 'half'
603+
});
604+
```
605+
606+
When using an async iterable or a `ReadableStream` as the request body, the `duplex` option must be set to `'half'`.
607+
608+
##### FormData with stream-backed Blob objects
609+
610+
`FormData` entries may include stream-backed `Blob` objects created from the filesystem, enabling efficient uploads of large files without buffering them in memory.
611+
```js
612+
import { openAsBlob } from 'node:fs';
613+
614+
const file = await openAsBlob('./large-file.csv');
615+
const form = new FormData();
616+
form.set('file', file, 'large-file.csv');
617+
618+
await fetch('https://example.com', { method: 'POST', body: form });
619+
```
620+
621+
#### Response Body Extensions
622+
623+
##### Async iterable response bodies
624+
625+
The `Response` constructor accepts async iterables, allowing flexible construction of streaming responses in server environments.
626+
```js
627+
const res = new Response(asyncIterable);
628+
```
629+
630+
#### CORS Behavior
631+
632+
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.
633+
634+
Applications requiring origin-based access control must implement these checks manually.
635+
636+
#### Header Restrictions
637+
638+
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.
639+
640+
#### Redirect Handling
641+
642+
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.
643+
644+
#### Resource Management and Garbage Collection
645+
646+
In Node.js, unconsumed response bodies may delay the release of underlying network resources. This can reduce connection reuse or cause stalls under load.
647+
648+
Always consume or cancel the response body:
649+
```js
650+
const res = await fetch(url);
651+
for await (const chunk of res.body) {
652+
// process chunk
653+
}
654+
```
655+
656+
For header-only requests, prefer `HEAD` to avoid creating a body:
657+
```js
658+
const headers = (await fetch(url, { method: 'HEAD' })).headers;
659+
```
660+
661+
#### Unsupported Features
662+
663+
##### `Expect: 100-continue`
664+
665+
The `Expect` request header is not supported. Request bodies are sent immediately, and `100 Continue` responses are ignored.
666+
667+
#### Implementation Notes
668+
669+
Node.js uses the [undici][] HTTP client internally to implement `fetch()`. The bundled version can be inspected with:
670+
```js
671+
console.log(process.versions.undici);
672+
```
673+
674+
For additional features—such as advanced agents, interceptors, or custom connection pooling—install `undici` as a separate dependency.
675+
676+
[WHATWG Fetch Standard]: https://fetch.spec.whatwg.org/
677+
[undici]: https://undici.nodejs.org/
678+
582679
## Class: `File`
583680

584681
<!-- YAML

0 commit comments

Comments
 (0)