This package provides highly likely functional and easy-to-use abstraction atop of native http(s).request and http2.request.
- Fetch-alike π₯
- Cool-beans π« config options (with defaults) π
- Automatic HTTP/2 support (ALPN negotiation) πΌ
- Automatic or opt-in body parse (with non-UTF-8 charset decoding) π
- Automatic and simplistic
Cookiestreatment (with TTL support) πͺ - Automatic body decoding (and opt-in request body encoding) ποΈ
- Better error management π₯
- Built-in streamable
FormDatainterface π - Support redirects & retries with fine-grained tune-ups πͺ
- Support plenty request body types (include blobs & streams) π¦
- Support both CJS and ESM module systems π§©
- Fully promise-able β³ and pipe-able π
- Zero dependencies π½
- Node.js
>= 20.0.0
npm install rekwest --saveimport rekwest, { constants } from 'rekwest';
const {
HTTP2_HEADER_AUTHORIZATION,
HTTP2_HEADER_CONTENT_ENCODING,
HTTP2_METHOD_POST,
HTTP_STATUS_OK,
} = constants;
const url = 'https://somewhe.re/somewhat/endpoint';
const res = await rekwest(url, {
body: { celestial: 'payload' },
headers: {
[HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
[HTTP2_HEADER_CONTENT_ENCODING]: 'br', // Enables: body encoding
/**
* [HTTP2_HEADER_CONTENT_TYPE] is undue for
* Array/Blob/File/FormData/Object/URLSearchParams body types
* and will be set automatically, with an option to override it here.
*/
},
method: HTTP2_METHOD_POST,
});
console.assert(res.statusCode === HTTP_STATUS_OK);
console.info(res.headers);
console.log(res.body);import { Readable } from 'node:stream';
import rekwest, {
constants,
Blob,
File,
FormData,
} from 'rekwest';
const {
HTTP2_HEADER_AUTHORIZATION,
HTTP2_HEADER_CONTENT_ENCODING,
HTTP2_METHOD_POST,
HTTP_STATUS_OK,
} = constants;
const blob = new Blob(['bits']);
const file = new File(['bits'], 'file.xyz');
const rbl = Readable.from('bits');
const rds = ReadableStream.from('bits');
const fd = new FormData({
aux: new Date(), // Either [[key, value]] or kv sequenceable
});
fd.append('celestial', 'payload');
fd.append('blob', blob, 'blob.xyz');
fd.append('file', file);
fd.append('rbl', rbl, 'rbl.xyz');
fd.append('rds', rds, 'rds.xyz');
/**
* Streamable entries are consumed on request submittion.
*/
const url = 'https://somewhe.re/somewhat/endpoint';
const res = await rekwest(url, {
body: fd,
headers: {
[HTTP2_HEADER_AUTHORIZATION]: 'Bearer [token]',
[HTTP2_HEADER_CONTENT_ENCODING]: 'zstd', // Enables: body encoding
},
method: HTTP2_METHOD_POST,
});
console.assert(res.statusCode === HTTP_STATUS_OK);
console.info(res.headers);
console.log(res.body);url{string | URL} The URL to send the request to.options{Object} Extends http(s).RequestOptions along with extra http2.ClientSessionOptions & http2.ClientSessionRequestOptions and tls.ConnectionOptions for HTTP/2 attunes.allowDowngrade{boolean}Default: falseControls whetherhttps:redirects tohttp:are allowed.baseURL{string | URL} The base URL to use in cases whereurlis a relative URL.body{string | Array | ArrayBuffer | ArrayBufferView | AsyncIterator | Blob | Buffer | DataView | File | FormData | Iterator | Object | Readable | ReadableStream | SharedArrayBuffer | URLSearchParams} The body to send with the request.bufferBody{boolean}Default: falseToggles the buffering of the streamable request bodies for redirects and retries.cookies{boolean | string | string[] | [k, v][] | Cookies | Object | URLSearchParams}Default: trueThe cookies to add to the request. Manually setcookieheader to override.cookiesTTL{boolean}Default: falseControls enablement of TTL for the cookies cache.credentials{include | omit | same-origin}Default: same-originControls credentials in case of cross-origin redirects.decodersOptions{Object} Configures decoders options, e.g.:brotli,zlib,zstd.digest{boolean}Default: trueControls whether to read the response stream or add a mixin.encodersOptions{Object} Configures encoders options, e.g.:brotli,zlib,zstd.follow{number}Default: 20The number of redirects to follow.h2{boolean}Default: falseForces the use of HTTP/2 protocol.headers{Object} The headers to add to the request.params{Object} The search params to add to theurl.parse{boolean}Default: trueControls whether to parse response body or return a buffer.redirect{error | follow | manual}Default: followControls the redirect flows.retry{Object} Represents the retry options.attempts{number}Default: 0The number of retry attempts.backoffStrategy{string}Default: interval * Math.log(Math.random() * (Math.E * Math.E - Math.E) + Math.E)The backoff strategy uses a log-uniform algorithm. To fix the interval, set the value tointerval * 1.errorCodes{string[]}Default: ['ECONNREFUSED', 'ECONNRESET', 'EHOSTDOWN', 'EHOSTUNREACH', 'ENETDOWN', 'ENETUNREACH', 'ENOTFOUND', 'ERR_HTTP2_STREAM_ERROR']The list of error codes to retry on.interval{number}Default: 1e3The initial retry interval.maxRetryAfter{number}Default: 3e5The maximumretry-afterlimit in milliseconds.retryAfter{boolean}Default: trueControlsretry-afterheader receptiveness.statusCodes{number[]}Default: [429, 500, 502, 503, 504]The list of status codes to retry on.
stripTrailingSlash{boolean}Default: falseControls whether to strip trailing slash at the end of the URL.thenable{boolean}Default: falseControls the promise resolutions.timeout{number}Default: 3e5The number of milliseconds a request can take before termination.trimTrailingSlashes{boolean}Default: falseControls whether to trim trailing slashes within the URL.
- Returns: Promise that resolves to
extended http.IncomingMessage
or http2.ClientHttp2Stream which is respectively
readable and duplex streams.
- if
digest: true&parse: truebody{string | Array | Buffer | Object} The body based on its content type.
- if
digest: falsearrayBuffer{AsyncFunction} Reads the response and returns ArrayBuffer.blob{AsyncFunction} Reads the response and returns Blob.body{AsyncFunction} Reads the response and returns Buffer ifparse: false.bytes{AsyncFunction} Reads the response and returns Uint8Array.json{AsyncFunction} Reads the response and returns Object.text{AsyncFunction} Reads the response and returns String.
bodyUsed{boolean} Indicates whether the response was read or not.cookies{undefined | Cookies} The cookies sent and received with the response.headers{Object} The headers received with the response.httpVersion{string} Indicates a protocol version negotiated with the server.ok{boolean} Indicates if the response was successful (statusCode: 200-299).redirected{boolean} Indicates if the response is the result of a redirect.statusCode{number} Indicates the status code of the response.trailers{undefined | Object} The trailer headers received with the response.
- if
The object to fulfill with default options.
The method to extend default options per instance.
import rekwest, { constants } from 'rekwest';
const {
HTTP_STATUS_OK,
} = constants;
const rk = rekwest.extend({
baseURL: 'https://somewhe.re',
});
const params = {
id: '[uid]',
signature: '[code]',
variant: '[any]',
};
const signal = AbortSignal.timeout(3e4);
const url = '/somewhat/endpoint';
const res = await rk(url, {
params,
signal,
});
console.assert(res.statusCode === HTTP_STATUS_OK);
console.info(res.headers);
console.log(res.body);The method with limited functionality to use with streams and/or pipes.
- No automata (redirects & retries).
- Pass
h2: truein options to use HTTP/2 protocol.- Use
ackn({ url: URL })method in advance to check the available protocols.
- Use
import fs from 'node:fs';
import { pipeline } from 'node:stream/promises';
import rekwest, {
ackn,
constants,
} from 'rekwest';
const {
HTTP2_METHOD_POST,
} = constants;
const url = new URL('https://somewhe.re/somewhat/endpoint');
const options = await ackn({ url });
await pipeline(
fs.createReadStream('/path/to/read/inlet.xyz'),
rekwest.stream(url, { ...options, method: HTTP2_METHOD_POST }),
fs.createWriteStream('/path/to/write/outlet.xyz'),
);For more details, please check tests (coverage: >97%) in the repository.