Repo of the Day
node-fetch/node-fetch
Published: Mar 2, 2023
Open repository ↗An oldie but a goodie I think. Using it for a script I just made that gets a static json file from a url and copies it to a local folder for mocking on VA. Probably not required since Node natively supports fetch, but good nonetheless to look at.
Summary
node-fetch is a lightweight JavaScript module that implements the WHATWG Fetch API for the Node.js runtime, so server-side code can use the same fetch() interface browsers expose. v3 is ESM-only and requires Node.js 12.20.0 or newer; v2 is still maintained for projects that need CommonJS require().
What it is useful for
node-fetch is useful when Node.js code needs to make HTTP or HTTPS calls using the browser-style fetch(url, options) rather than the built-in http/https modules. It returns a Response whose body can be read with response.text(), response.json(), response.arrayBuffer(), response.blob(), or response.formData(), and response.body is a native Node Readable stream that can be piped elsewhere.
Jobs it fits:
- Calling REST APIs and parsing JSON with
await response.json() - POSTing form data via
URLSearchParams(theContent-Typeis set automatically only when an instance is passed) - POSTing JSON by stringifying the object and setting the header manually
- POSTing files via
fileFromSync(), or building multipart payloads with the spec-compliantFormData,File, andBlobit ships - Streaming large responses via
stream.pipeline(response.body, writable)orfor await (const chunk of response.body) - Canceling requests with
AbortController/AbortSignal, catching the exportedAbortError - Passing a custom
http/httpsAgentthrough theagentoption for keep-alive, self-signed certificates, or custom DNS
How engineers can use it
Install with npm install node-fetch. Import in ESM as import fetch from 'node-fetch'.
GET JSON:
import fetch from 'node-fetch';
const response = await fetch('https://api.github.com/users/github');
const data = await response.json();
POST multipart:
import fetch, { FormData, File } from 'node-fetch';
const formData = new FormData();
const abc = new File([new Uint8Array([97, 98, 99])], 'abc.txt', { type: 'text/plain' });
formData.set('file-upload', abc, 'new name.txt');
const response = await fetch('https://httpbin.org/post', { method: 'POST', body: formData });
Stream a binary response to disk:
import { createWriteStream } from 'node:fs';
import { pipeline } from 'node:stream';
import { promisify } from 'node:util';
import fetch from 'node-fetch';
const streamPipeline = promisify(pipeline);
const response = await fetch('https://github.githubassets.com/images/modules/logos_page/Octocat.png');
if (!response.ok) throw new Error(`unexpected response ${response.statusText}`);
await streamPipeline(response.body, createWriteStream('./octocat.png'));
Documented limitations to plan around: 3xx-5xx responses are not exceptions (check response.ok or throw your own); cookies are not stored automatically and must be pulled from response.headers.raw()['set-cookie']; and the Request class does not implement type, destination, mode, credentials, cache, integrity, or keepalive. v3 cannot be require()d — the README's workaround is const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); from CommonJS, or stay on node-fetch@2.