UNPKG

28.8 kBMarkdownView Raw
1<div align="center">
2 <img src="docs/media/Banner.svg" alt="Node Fetch"/>
3 <br>
4 <p>A light-weight module that brings <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">Fetch API</a> to Node.js.</p>
5 <a href="https://github.com/node-fetch/node-fetch/actions"><img src="https://github.com/node-fetch/node-fetch/workflows/CI/badge.svg?branch=master" alt="Build status"></a>
6 <a href="https://coveralls.io/github/node-fetch/node-fetch"><img src="https://img.shields.io/coveralls/github/node-fetch/node-fetch" alt="Coverage status"></a>
7 <a href="https://packagephobia.now.sh/result?p=node-fetch"><img src="https://badgen.net/packagephobia/install/node-fetch" alt="Current version"></a>
8 <a href="https://www.npmjs.com/package/node-fetch"><img src="https://img.shields.io/npm/v/node-fetch" alt="Install size"></a>
9 <a href="https://github.com/sindresorhus/awesome-nodejs"><img src="https://awesome.re/mentioned-badge.svg" alt="Mentioned in Awesome Node.js"></a>
10 <a href="https://discord.gg/Zxbndcm"><img src="https://img.shields.io/discord/619915844268326952?color=%237289DA&label=Discord" alt="Discord"></a>
11 <br>
12 <br>
13 <b>Consider supporting us on our Open Collective:</b>
14 <br>
15 <br>
16 <a href="https://opencollective.com/node-fetch"><img src="https://opencollective.com/node-fetch/donate/button.png?color=blue" alt="Open Collective"></a>
17</div>
18
19---
20
21**You might be looking for the [v2 docs](https://github.com/node-fetch/node-fetch/tree/2.x#readme)**
22
23<!-- TOC -->
24
25- [Motivation](#motivation)
26- [Features](#features)
27- [Difference from client-side fetch](#difference-from-client-side-fetch)
28- [Installation](#installation)
29- [Loading and configuring the module](#loading-and-configuring-the-module)
30- [Upgrading](#upgrading)
31- [Common Usage](#common-usage)
32 - [Plain text or HTML](#plain-text-or-html)
33 - [JSON](#json)
34 - [Simple Post](#simple-post)
35 - [Post with JSON](#post-with-json)
36 - [Post with form parameters](#post-with-form-parameters)
37 - [Handling exceptions](#handling-exceptions)
38 - [Handling client and server errors](#handling-client-and-server-errors)
39 - [Handling cookies](#handling-cookies)
40- [Advanced Usage](#advanced-usage)
41 - [Streams](#streams)
42 - [Accessing Headers and other Metadata](#accessing-headers-and-other-metadata)
43 - [Extract Set-Cookie Header](#extract-set-cookie-header)
44 - [Post data using a file](#post-data-using-a-file)
45 - [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal)
46- [API](#api)
47 - [fetch(url[, options])](#fetchurl-options)
48 - [Options](#options)
49 - [Default Headers](#default-headers)
50 - [Custom Agent](#custom-agent)
51 - [Custom highWaterMark](#custom-highwatermark)
52 - [Insecure HTTP Parser](#insecure-http-parser)
53 - [Class: Request](#class-request)
54 - [new Request(input[, options])](#new-requestinput-options)
55 - [Class: Response](#class-response)
56 - [new Response([body[, options]])](#new-responsebody-options)
57 - [response.ok](#responseok)
58 - [response.redirected](#responseredirected)
59 - [response.type](#responsetype)
60 - [Class: Headers](#class-headers)
61 - [new Headers([init])](#new-headersinit)
62 - [Interface: Body](#interface-body)
63 - [body.body](#bodybody)
64 - [body.bodyUsed](#bodybodyused)
65 - [body.arrayBuffer()](#bodyarraybuffer)
66 - [body.blob()](#bodyblob)
67 - [body.formData()](#formdata)
68 - [body.json()](#bodyjson)
69 - [body.text()](#bodytext)
70 - [Class: FetchError](#class-fetcherror)
71 - [Class: AbortError](#class-aborterror)
72- [TypeScript](#typescript)
73- [Acknowledgement](#acknowledgement)
74- [Team](#team)
75 - [Former](#former)
76- [License](#license)
77
78<!-- /TOC -->
79
80## Motivation
81
82Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), why not go from native `http` to `fetch` API directly? Hence, `node-fetch`, minimal code for a `window.fetch` compatible API on Node.js runtime.
83
84See Jason Miller's [isomorphic-unfetch](https://www.npmjs.com/package/isomorphic-unfetch) or Leonardo Quixada's [cross-fetch](https://github.com/lquixada/cross-fetch) for isomorphic usage (exports `node-fetch` for server-side, `whatwg-fetch` for client-side).
85
86## Features
87
88- Stay consistent with `window.fetch` API.
89- Make conscious trade-off when following [WHATWG fetch spec][whatwg-fetch] and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known differences.
90- Use native promise and async functions.
91- Use native Node streams for body, on both request and response.
92- Decode content encoding (gzip/deflate/brotli) properly, and convert string output (such as `res.text()` and `res.json()`) to UTF-8 automatically.
93- Useful extensions such as redirect limit, response size limit, [explicit errors][error-handling.md] for troubleshooting.
94
95## Difference from client-side fetch
96
97- See known differences:
98 - [As of v3.x](docs/v3-LIMITS.md)
99 - [As of v2.x](docs/v2-LIMITS.md)
100- If you happen to use a missing feature that `window.fetch` offers, feel free to open an issue.
101- Pull requests are welcomed too!
102
103## Installation
104
105Current stable release (`3.x`) requires at least Node.js 12.20.0.
106
107```sh
108npm install node-fetch
109```
110
111## Loading and configuring the module
112
113### ES Modules (ESM)
114
115```js
116import fetch from 'node-fetch';
117```
118
119### CommonJS
120
121`node-fetch` from v3 is an ESM-only module - you are not able to import it with `require()`.
122
123If you cannot switch to ESM, please use v2 which remains compatible with CommonJS. Critical bug fixes will continue to be published for v2.
124
125```sh
126npm install node-fetch@2
127```
128
129Alternatively, you can use the async `import()` function from CommonJS to load `node-fetch` asynchronously:
130
131```js
132// mod.cjs
133const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
134```
135
136### Providing global access
137
138To use `fetch()` without importing it, you can patch the `global` object in node:
139
140```js
141// fetch-polyfill.js
142import fetch, {
143 Blob,
144 blobFrom,
145 blobFromSync,
146 File,
147 fileFrom,
148 fileFromSync,
149 FormData,
150 Headers,
151 Request,
152 Response,
153} from 'node-fetch'
154
155if (!globalThis.fetch) {
156 globalThis.fetch = fetch
157 globalThis.Headers = Headers
158 globalThis.Request = Request
159 globalThis.Response = Response
160}
161
162// index.js
163import './fetch-polyfill'
164
165// ...
166```
167
168## Upgrading
169
170Using an old version of node-fetch? Check out the following files:
171
172- [2.x to 3.x upgrade guide](docs/v3-UPGRADE-GUIDE.md)
173- [1.x to 2.x upgrade guide](docs/v2-UPGRADE-GUIDE.md)
174- [Changelog](https://github.com/node-fetch/node-fetch/releases)
175
176## Common Usage
177
178NOTE: The documentation below is up-to-date with `3.x` releases, if you are using an older version, please check how to [upgrade](#upgrading).
179
180### Plain text or HTML
181
182```js
183import fetch from 'node-fetch';
184
185const response = await fetch('https://github.com/');
186const body = await response.text();
187
188console.log(body);
189```
190
191### JSON
192
193```js
194import fetch from 'node-fetch';
195
196const response = await fetch('https://api.github.com/users/github');
197const data = await response.json();
198
199console.log(data);
200```
201
202### Simple Post
203
204```js
205import fetch from 'node-fetch';
206
207const response = await fetch('https://httpbin.org/post', {method: 'POST', body: 'a=1'});
208const data = await response.json();
209
210console.log(data);
211```
212
213### Post with JSON
214
215```js
216import fetch from 'node-fetch';
217
218const body = {a: 1};
219
220const response = await fetch('https://httpbin.org/post', {
221 method: 'post',
222 body: JSON.stringify(body),
223 headers: {'Content-Type': 'application/json'}
224});
225const data = await response.json();
226
227console.log(data);
228```
229
230### Post with form parameters
231
232`URLSearchParams` is available on the global object in Node.js as of v10.0.0. See [official documentation](https://nodejs.org/api/url.html#url_class_urlsearchparams) for more usage methods.
233
234NOTE: The `Content-Type` header is only set automatically to `x-www-form-urlencoded` when an instance of `URLSearchParams` is given as such:
235
236```js
237import fetch from 'node-fetch';
238
239const params = new URLSearchParams();
240params.append('a', 1);
241
242const response = await fetch('https://httpbin.org/post', {method: 'POST', body: params});
243const data = await response.json();
244
245console.log(data);
246```
247
248### Handling exceptions
249
250NOTE: 3xx-5xx responses are _NOT_ exceptions, and should be handled in `then()`, see the next section.
251
252Wrapping the fetch function into a `try/catch` block will catch _all_ exceptions, such as errors originating from node core libraries, like network errors, and operational errors which are instances of FetchError. See the [error handling document][error-handling.md] for more details.
253
254```js
255import fetch from 'node-fetch';
256
257try {
258 await fetch('https://domain.invalid/');
259} catch (error) {
260 console.log(error);
261}
262```
263
264### Handling client and server errors
265
266It is common to create a helper function to check that the response contains no client (4xx) or server (5xx) error responses:
267
268```js
269import fetch from 'node-fetch';
270
271class HTTPResponseError extends Error {
272 constructor(response, ...args) {
273 super(`HTTP Error Response: ${response.status} ${response.statusText}`, ...args);
274 this.response = response;
275 }
276}
277
278const checkStatus = response => {
279 if (response.ok) {
280 // response.status >= 200 && response.status < 300
281 return response;
282 } else {
283 throw new HTTPResponseError(response);
284 }
285}
286
287const response = await fetch('https://httpbin.org/status/400');
288
289try {
290 checkStatus(response);
291} catch (error) {
292 console.error(error);
293
294 const errorBody = await error.response.text();
295 console.error(`Error body: ${errorBody}`);
296}
297```
298
299### Handling cookies
300
301Cookies are not stored by default. However, cookies can be extracted and passed by manipulating request and response headers. See [Extract Set-Cookie Header](#extract-set-cookie-header) for details.
302
303## Advanced Usage
304
305### Streams
306
307The "Node.js way" is to use streams when possible. You can pipe `res.body` to another stream. This example uses [stream.pipeline](https://nodejs.org/api/stream.html#stream_stream_pipeline_streams_callback) to attach stream error handlers and wait for the download to complete.
308
309```js
310import {createWriteStream} from 'node:fs';
311import {pipeline} from 'node:stream';
312import {promisify} from 'node:util'
313import fetch from 'node-fetch';
314
315const streamPipeline = promisify(pipeline);
316
317const response = await fetch('https://github.githubassets.com/images/modules/logos_page/Octocat.png');
318
319if (!response.ok) throw new Error(`unexpected response ${response.statusText}`);
320
321await streamPipeline(response.body, createWriteStream('./octocat.png'));
322```
323
324In Node.js 14 you can also use async iterators to read `body`; however, be careful to catch
325errors -- the longer a response runs, the more likely it is to encounter an error.
326
327```js
328import fetch from 'node-fetch';
329
330const response = await fetch('https://httpbin.org/stream/3');
331
332try {
333 for await (const chunk of response.body) {
334 console.dir(JSON.parse(chunk.toString()));
335 }
336} catch (err) {
337 console.error(err.stack);
338}
339```
340
341In Node.js 12 you can also use async iterators to read `body`; however, async iterators with streams
342did not mature until Node.js 14, so you need to do some extra work to ensure you handle errors
343directly from the stream and wait on it response to fully close.
344
345```js
346import fetch from 'node-fetch';
347
348const read = async body => {
349 let error;
350 body.on('error', err => {
351 error = err;
352 });
353
354 for await (const chunk of body) {
355 console.dir(JSON.parse(chunk.toString()));
356 }
357
358 return new Promise((resolve, reject) => {
359 body.on('close', () => {
360 error ? reject(error) : resolve();
361 });
362 });
363};
364
365try {
366 const response = await fetch('https://httpbin.org/stream/3');
367 await read(response.body);
368} catch (err) {
369 console.error(err.stack);
370}
371```
372
373### Accessing Headers and other Metadata
374
375```js
376import fetch from 'node-fetch';
377
378const response = await fetch('https://github.com/');
379
380console.log(response.ok);
381console.log(response.status);
382console.log(response.statusText);
383console.log(response.headers.raw());
384console.log(response.headers.get('content-type'));
385```
386
387### Extract Set-Cookie Header
388
389Unlike browsers, you can access raw `Set-Cookie` headers manually using `Headers.raw()`. This is a `node-fetch` only API.
390
391```js
392import fetch from 'node-fetch';
393
394const response = await fetch('https://example.com');
395
396// Returns an array of values, instead of a string of comma-separated values
397console.log(response.headers.raw()['set-cookie']);
398```
399
400### Post data using a file
401
402```js
403import fetch {
404 Blob,
405 blobFrom,
406 blobFromSync,
407 File,
408 fileFrom,
409 fileFromSync,
410} from 'node-fetch'
411
412const mimetype = 'text/plain'
413const blob = fileFromSync('./input.txt', mimetype)
414const url = 'https://httpbin.org/post'
415
416const response = await fetch(url, { method: 'POST', body: blob })
417const data = await response.json()
418
419console.log(data)
420```
421
422node-fetch comes with a spec-compliant [FormData] implementations for posting
423multipart/form-data payloads
424
425```js
426import fetch, { FormData, File, fileFrom } from 'node-fetch'
427
428const httpbin = 'https://httpbin.org/post'
429const formData = new FormData()
430const binary = new Uint8Array([ 97, 98, 99 ])
431const abc = new File([binary], 'abc.txt', { type: 'text/plain' })
432
433formData.set('greeting', 'Hello, world!')
434formData.set('file-upload', abc, 'new name.txt')
435
436const response = await fetch(httpbin, { method: 'POST', body: formData })
437const data = await response.json()
438
439console.log(data)
440```
441
442If you for some reason need to post a stream coming from any arbitrary place,
443then you can append a [Blob] or a [File] look-a-like item.
444
445The minimum requirement is that it has:
4461. A `Symbol.toStringTag` getter or property that is either `Blob` or `File`
4472. A known size.
4483. And either a `stream()` method or a `arrayBuffer()` method that returns a ArrayBuffer.
449
450The `stream()` must return any async iterable object as long as it yields Uint8Array (or Buffer)
451so Node.Readable streams and whatwg streams works just fine.
452
453```js
454formData.append('upload', {
455 [Symbol.toStringTag]: 'Blob',
456 size: 3,
457 *stream() {
458 yield new Uint8Array([97, 98, 99])
459 },
460 arrayBuffer() {
461 return new Uint8Array([97, 98, 99]).buffer
462 }
463}, 'abc.txt')
464```
465
466### Request cancellation with AbortSignal
467
468You may cancel requests with `AbortController`. A suggested implementation is [`abort-controller`](https://www.npmjs.com/package/abort-controller).
469
470An example of timing out a request after 150ms could be achieved as the following:
471
472```js
473import fetch, { AbortError } from 'node-fetch';
474
475// AbortController was added in node v14.17.0 globally
476const AbortController = globalThis.AbortController || await import('abort-controller')
477
478const controller = new AbortController();
479const timeout = setTimeout(() => {
480 controller.abort();
481}, 150);
482
483try {
484 const response = await fetch('https://example.com', {signal: controller.signal});
485 const data = await response.json();
486} catch (error) {
487 if (error instanceof AbortError) {
488 console.log('request was aborted');
489 }
490} finally {
491 clearTimeout(timeout);
492}
493```
494
495See [test cases](https://github.com/node-fetch/node-fetch/blob/master/test/) for more examples.
496
497## API
498
499### fetch(url[, options])
500
501- `url` A string representing the URL for fetching
502- `options` [Options](#fetch-options) for the HTTP(S) request
503- Returns: <code>Promise&lt;[Response](#class-response)&gt;</code>
504
505Perform an HTTP(S) fetch.
506
507`url` should be an absolute URL, such as `https://example.com/`. A path-relative URL (`/file/under/root`) or protocol-relative URL (`//can-be-http-or-https.com/`) will result in a rejected `Promise`.
508
509<a id="fetch-options"></a>
510
511### Options
512
513The default values are shown after each option key.
514
515```js
516{
517 // These properties are part of the Fetch Standard
518 method: 'GET',
519 headers: {}, // Request headers. format is the identical to that accepted by the Headers constructor (see below)
520 body: null, // Request body. can be null, or a Node.js Readable stream
521 redirect: 'follow', // Set to `manual` to extract redirect headers, `error` to reject redirect
522 signal: null, // Pass an instance of AbortSignal to optionally abort requests
523
524 // The following properties are node-fetch extensions
525 follow: 20, // maximum redirect count. 0 to not follow redirect
526 compress: true, // support gzip/deflate content encoding. false to disable
527 size: 0, // maximum response body size in bytes. 0 to disable
528 agent: null, // http(s).Agent instance or function that returns an instance (see below)
529 highWaterMark: 16384, // the maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource.
530 insecureHTTPParser: false // Use an insecure HTTP parser that accepts invalid HTTP headers when `true`.
531}
532```
533
534#### Default Headers
535
536If no values are set, the following request headers will be sent automatically:
537
538| Header | Value |
539| ------------------- | ------------------------------------------------------ |
540| `Accept-Encoding` | `gzip, deflate, br` (when `options.compress === true`) |
541| `Accept` | `*/*` |
542| `Connection` | `close` _(when no `options.agent` is present)_ |
543| `Content-Length` | _(automatically calculated, if possible)_ |
544| `Host` | _(host and port information from the target URI)_ |
545| `Transfer-Encoding` | `chunked` _(when `req.body` is a stream)_ |
546| `User-Agent` | `node-fetch` |
547
548
549Note: when `body` is a `Stream`, `Content-Length` is not set automatically.
550
551#### Custom Agent
552
553The `agent` option allows you to specify networking related options which are out of the scope of Fetch, including and not limited to the following:
554
555- Support self-signed certificate
556- Use only IPv4 or IPv6
557- Custom DNS Lookup
558
559See [`http.Agent`](https://nodejs.org/api/http.html#http_new_agent_options) for more information.
560
561In addition, the `agent` option accepts a function that returns `http`(s)`.Agent` instance given current [URL](https://nodejs.org/api/url.html), this is useful during a redirection chain across HTTP and HTTPS protocol.
562
563```js
564import http from 'node:http';
565import https from 'node:https';
566
567const httpAgent = new http.Agent({
568 keepAlive: true
569});
570const httpsAgent = new https.Agent({
571 keepAlive: true
572});
573
574const options = {
575 agent: function(_parsedURL) {
576 if (_parsedURL.protocol == 'http:') {
577 return httpAgent;
578 } else {
579 return httpsAgent;
580 }
581 }
582};
583```
584
585<a id="custom-highWaterMark"></a>
586
587#### Custom highWaterMark
588
589Stream on Node.js have a smaller internal buffer size (16kB, aka `highWaterMark`) from client-side browsers (>1MB, not consistent across browsers). Because of that, when you are writing an isomorphic app and using `res.clone()`, it will hang with large response in Node.
590
591The recommended way to fix this problem is to resolve cloned response in parallel:
592
593```js
594import fetch from 'node-fetch';
595
596const response = await fetch('https://example.com');
597const r1 = response.clone();
598
599const results = await Promise.all([response.json(), r1.text()]);
600
601console.log(results[0]);
602console.log(results[1]);
603```
604
605If for some reason you don't like the solution above, since `3.x` you are able to modify the `highWaterMark` option:
606
607```js
608import fetch from 'node-fetch';
609
610const response = await fetch('https://example.com', {
611 // About 1MB
612 highWaterMark: 1024 * 1024
613});
614
615const result = await res.clone().arrayBuffer();
616console.dir(result);
617```
618
619#### Insecure HTTP Parser
620
621Passed through to the `insecureHTTPParser` option on http(s).request. See [`http.request`](https://nodejs.org/api/http.html#http_http_request_url_options_callback) for more information.
622
623#### Manual Redirect
624
625The `redirect: 'manual'` option for node-fetch is different from the browser & specification, which
626results in an [opaque-redirect filtered response](https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect).
627node-fetch gives you the typical [basic filtered response](https://fetch.spec.whatwg.org/#concept-filtered-response-basic) instead.
628
629```js
630const fetch = require('node-fetch');
631
632const response = await fetch('https://httpbin.org/status/301', { redirect: 'manual' });
633
634if (response.status === 301 || response.status === 302) {
635 const locationURL = new URL(response.headers.get('location'), response.url);
636 const response2 = await fetch(locationURL, { redirect: 'manual' });
637 console.dir(response2);
638}
639```
640
641<a id="class-request"></a>
642
643### Class: Request
644
645An HTTP(S) request containing information about URL, method, headers, and the body. This class implements the [Body](#iface-body) interface.
646
647Due to the nature of Node.js, the following properties are not implemented at this moment:
648
649- `type`
650- `destination`
651- `mode`
652- `credentials`
653- `cache`
654- `integrity`
655- `keepalive`
656
657The following node-fetch extension properties are provided:
658
659- `follow`
660- `compress`
661- `counter`
662- `agent`
663- `highWaterMark`
664
665See [options](#fetch-options) for exact meaning of these extensions.
666
667#### new Request(input[, options])
668
669<small>_(spec-compliant)_</small>
670
671- `input` A string representing a URL, or another `Request` (which will be cloned)
672- `options` [Options](#fetch-options) for the HTTP(S) request
673
674Constructs a new `Request` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request).
675
676In most cases, directly `fetch(url, options)` is simpler than creating a `Request` object.
677
678<a id="class-response"></a>
679
680### Class: Response
681
682An HTTP(S) response. This class implements the [Body](#iface-body) interface.
683
684The following properties are not implemented in node-fetch at this moment:
685
686- `trailer`
687
688#### new Response([body[, options]])
689
690<small>_(spec-compliant)_</small>
691
692- `body` A `String` or [`Readable` stream][node-readable]
693- `options` A [`ResponseInit`][response-init] options dictionary
694
695Constructs a new `Response` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response).
696
697Because Node.js does not implement service workers (for which this class was designed), one rarely has to construct a `Response` directly.
698
699#### response.ok
700
701<small>_(spec-compliant)_</small>
702
703Convenience property representing if the request ended normally. Will evaluate to true if the response status was greater than or equal to 200 but smaller than 300.
704
705#### response.redirected
706
707<small>_(spec-compliant)_</small>
708
709Convenience property representing if the request has been redirected at least once. Will evaluate to true if the internal redirect counter is greater than 0.
710
711#### response.type
712
713<small>_(deviation from spec)_</small>
714
715Convenience property representing the response's type. node-fetch only supports `'default'` and `'error'` and does not make use of [filtered responses](https://fetch.spec.whatwg.org/#concept-filtered-response).
716
717<a id="class-headers"></a>
718
719### Class: Headers
720
721This class allows manipulating and iterating over a set of HTTP headers. All methods specified in the [Fetch Standard][whatwg-fetch] are implemented.
722
723#### new Headers([init])
724
725<small>_(spec-compliant)_</small>
726
727- `init` Optional argument to pre-fill the `Headers` object
728
729Construct a new `Headers` object. `init` can be either `null`, a `Headers` object, an key-value map object or any iterable object.
730
731```js
732// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class
733import {Headers} from 'node-fetch';
734
735const meta = {
736 'Content-Type': 'text/xml'
737};
738const headers = new Headers(meta);
739
740// The above is equivalent to
741const meta = [['Content-Type', 'text/xml']];
742const headers = new Headers(meta);
743
744// You can in fact use any iterable objects, like a Map or even another Headers
745const meta = new Map();
746meta.set('Content-Type', 'text/xml');
747const headers = new Headers(meta);
748const copyOfHeaders = new Headers(headers);
749```
750
751<a id="iface-body"></a>
752
753### Interface: Body
754
755`Body` is an abstract interface with methods that are applicable to both `Request` and `Response` classes.
756
757#### body.body
758
759<small>_(deviation from spec)_</small>
760
761- Node.js [`Readable` stream][node-readable]
762
763Data are encapsulated in the `Body` object. Note that while the [Fetch Standard][whatwg-fetch] requires the property to always be a WHATWG `ReadableStream`, in node-fetch it is a Node.js [`Readable` stream][node-readable].
764
765#### body.bodyUsed
766
767<small>_(spec-compliant)_</small>
768
769- `Boolean`
770
771A boolean property for if this body has been consumed. Per the specs, a consumed body cannot be used again.
772
773#### body.arrayBuffer()
774
775#### body.formData()
776
777#### body.blob()
778
779#### body.json()
780
781#### body.text()
782
783`fetch` comes with methods to parse `multipart/form-data` payloads as well as
784`x-www-form-urlencoded` bodies using `.formData()` this comes from the idea that
785Service Worker can intercept such messages before it's sent to the server to
786alter them. This is useful for anybody building a server so you can use it to
787parse & consume payloads.
788
789<details>
790<summary>Code example</summary>
791
792```js
793import http from 'node:http'
794import { Response } from 'node-fetch'
795
796http.createServer(async function (req, res) {
797 const formData = await new Response(req, {
798 headers: req.headers // Pass along the boundary value
799 }).formData()
800 const allFields = [...formData]
801
802 const file = formData.get('uploaded-files')
803 const arrayBuffer = await file.arrayBuffer()
804 const text = await file.text()
805 const whatwgReadableStream = file.stream()
806
807 // other was to consume the request could be to do:
808 const json = await new Response(req).json()
809 const text = await new Response(req).text()
810 const arrayBuffer = await new Response(req).arrayBuffer()
811 const blob = await new Response(req, {
812 headers: req.headers // So that `type` inherits `Content-Type`
813 }.blob()
814})
815```
816
817</details>
818
819<a id="class-fetcherror"></a>
820
821### Class: FetchError
822
823<small>_(node-fetch extension)_</small>
824
825An operational error in the fetching process. See [ERROR-HANDLING.md][] for more info.
826
827<a id="class-aborterror"></a>
828
829### Class: AbortError
830
831<small>_(node-fetch extension)_</small>
832
833An Error thrown when the request is aborted in response to an `AbortSignal`'s `abort` event. It has a `name` property of `AbortError`. See [ERROR-HANDLING.MD][] for more info.
834
835## TypeScript
836
837**Since `3.x` types are bundled with `node-fetch`, so you don't need to install any additional packages.**
838
839For older versions please use the type definitions from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped):
840
841```sh
842npm install --save-dev @types/node-fetch@2.x
843```
844
845## Acknowledgement
846
847Thanks to [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference.
848
849## Team
850
851| [![David Frank](https://github.com/bitinn.png?size=100)](https://github.com/bitinn) | [![Jimmy Wärting](https://github.com/jimmywarting.png?size=100)](https://github.com/jimmywarting) | [![Antoni Kepinski](https://github.com/xxczaki.png?size=100)](https://github.com/xxczaki) | [![Richie Bendall](https://github.com/Richienb.png?size=100)](https://github.com/Richienb) | [![Gregor Martynus](https://github.com/gr2m.png?size=100)](https://github.com/gr2m) |
852| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
853| [David Frank](https://bitinn.net/) | [Jimmy Wärting](https://jimmy.warting.se/) | [Antoni Kepinski](https://kepinski.ch) | [Richie Bendall](https://www.richie-bendall.ml/) | [Gregor Martynus](https://twitter.com/gr2m) |
854
855###### Former
856
857- [Timothy Gu](https://github.com/timothygu)
858- [Jared Kantrowitz](https://github.com/jkantr)
859
860## License
861
862[MIT](LICENSE.md)
863
864[whatwg-fetch]: https://fetch.spec.whatwg.org/
865[response-init]: https://fetch.spec.whatwg.org/#responseinit
866[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams
867[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers
868[error-handling.md]: https://github.com/node-fetch/node-fetch/blob/master/docs/ERROR-HANDLING.md
869[FormData]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
870[Blob]: https://developer.mozilla.org/en-US/docs/Web/API/Blob
871[File]: https://developer.mozilla.org/en-US/docs/Web/API/File