Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
http-factory
Advanced tools
A declarative way to instantiate http interfaces and make iterable requests
http-factory
is an NPM library and Axios-wrapper that offers a declarative way to instantiate http interfaces and make iterable (serial async) requests.
const data = [];
for await (const rs of client.serialGet(urls)) {
if (rs.status === 200) data.push({ data: rs.data });
...
See the API docs below for instantiating clients, dev logging, and making iterable requests.
For client options see Axios docs.
http-factory
currently supports UMD, CommonJS (node versions >= 10), and ESM build-targets. Is your preferred build not supported? Open an issue!
npm install http-factory
# OR
yarn add http-factory
Commonjs:
const { httpClient } = require('http-factory');
ESM:
import { httpClient } from 'http-factory';
By default, requests are sent with a Content-Type header of application/json. UTF-8 encoding is set by default, and all request bodies will be serialized.
To change this behavior, you can provide your own Axios options to the constructor:
const client = new HttpClient({ baseURL: 'https://some-domain.com/api/' });
You can chain interceptors, transformers, and dev loggers onto the client object:
const client = new HttpClient({ ...options })
.transforms({ request: fn, response: fn })
.intercepts({ request: fn, response: fn, error: fn })
.logs({ request: true, response: true })
.setBaseUrl('...');
Note Interceptors expect response and error handlers to be passed together.
set a base URL for the given client instance
Example
const client = new HttpClient({ ...options })
.setBaseUrl('https://website.com/api');
register handlers for intercepting request / response
Expects named arguments to which request, response, and error interceptors will be passed.
Note Response and error each require the other. This will be fixed in v1.0.3
Example
import { request, response, error } from './interceptors';
const client = new HttpClient({ ...options })
.intercepts({ request, response, error });
register request / response transformers
Executes handlers on inbound / outbound request objects; fires before interceptors. Accepts Function or array thereof.
Transformers are invoked before interceptors and automatically deserialize responses, where applicable.
Example
import { request, response } from './transformers';
const client = new HttpClient({ ...options })
.transforms({ request, response });
toggle request/response logging
Specify whether you want to log the request and / or response headers and data.
Example
const isDevEnv = process.env.NODE_ENV === 'development';
const client = new HttpClient({ ...options })
.logs({ request: isDevEnv, response: isDevEnv }); // logs request / response to console in dev env
Iterable requests allow the execution of n HTTP requests serially. Note these methods have fail-fast behaviors - much akin to Promise.all
, if one of the requests fails, the chain stops. It is recommended to either use try...catch
blocks around these iterations, or client.intercepts({ ... })
to process erroneous responses.
In order to bypass fail-fast behavior and lazily collect all erroneous responses, use continuation-passing style by passing a callback. Errors will be instances of the Error constructor whereas Http requests with a 4xx status will be regular objects.
execute an iterable request, awaiting each result in sequence
Pass an array of objects (each a GET config) and iterate over the results as they resolve (or reject).
Example
const client = new HttpClient({ ...options });
const results = [];
const urls : [{ url: '/users/1' }, { url: '/users/2' }, { url: '/users/3' }];
async function fetchAll () {
for await (const response of client.serialGet(urls)) {
try {
if (response.status === 200) results.push({ data: response.data.id });
// [ { data: 1 } ]
// [ { data: 1 }, { data: 2 } ]
// [ { data: 1 }, { data: 2 }, { data: 3 } ]
...
}
}
execute an iterable request, awaiting each result in sequence
Pass an array of objects (each a POST config) and iterate over the results as they resolve (or reject).
Example
...
async function postAll () {
for await (const { status } of client.serialPost(configs)) {
try {
if (status === 201) results.push({ ok: true });
// [ { ok: true } ]
// [ { ok: true }, { ok: true } ]
// [ { ok: true }, { ok: true }, { ok: true } ]
} catch (ex) {
results.push({ ok: false });
}
...
}
...
}
execute an iterable request, awaiting each result in sequence
Pass an array of objects (each a PUT config) and iterate over the results as they resolve (or reject).
Example
const client = new HttpClient({ ...options });
const results = [];
const configs = [{
url: 'http://database/people/6',
data: { name: 'Egon Schiele' }
},
{
url: 'http://database/people/5',
data: { name: 'Ludwig Wittgenstein' }
},
{ ... }
];
async function putAll () {
for await (const { status } of client.serialPut(configs)) {
try {
if (status === 204) results.push({ ok: true });
// [ { ok: true } ]
// [ { ok: true }, { ok: true } ]
// [ { ok: true }, { ok: true }, { ok: true } ]
} catch (ex) {
results.push({ ok: false });
}
...
}
...
const success = results.reduce((acc, { ok }) => acc = !!ok && true);
}
execute an iterable request, awaiting each result in sequence
Pass an array of objects (each a DELETE config) and iterate over the results as they resolve (or reject).
Example
...
async function deleteAll () {
for await (const { status } of client.serialDelete(configs)) {
try {
if (status === 204) results.push({ ok: true });
// [ { ok: true } ]
// [ { ok: true }, { ok: true } ]
// [ { ok: true }, { ok: true }, { ok: true } ]
} catch (ex) {
results.push({ ok: false });
}
...
}
...
}
Each request method accepts an optional callback to which the response or error will be piped. This affords the use of continuation-passing using callbacks:
Example
async function getData () {
await client.getTheData({ url }, ({ ok, data }) => {
if (ok) this.data = data;
else ...
});
}
Continuations can likewise be passed to serial requests:
Serial Request Example
...
const callback = ({ data }) => results.push(data);
async function fetchAll () {
try {
for await (const _ of client.serialGet(urls, callback));
} catch(ex) { ... }
}
...
FAQs
declarative, strongly-typed http clients and serial requests
The npm package http-factory receives a total of 1 weekly downloads. As such, http-factory popularity was classified as not popular.
We found that http-factory demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.