// Native const { parse } = require("url"); const http = require("http"); const https = require("https"); // Packages const fetch = require("node-fetch"); /** * Returns a `fetch` version with a similar * API to the browser's configured with a * HTTP2 agent. * * It encodes `body` automatically as JSON. * * @param {String} host * @return {Function} fetch */ module.exports = class Agent { constructor(url, { tls = true, debug } = {}) { this._url = url; const parsed = parse(url); this._protocol = parsed.protocol; this._debug = debug; if (tls) { this._initAgent(); } } _initAgent() { const module = this._protocol === "https:" ? https : http; const agent = (this._agent = new module.Agent({ keepAlive: true, keepAliveMsecs: 10000, maxSockets: 8 }).on("error", err => this._onError(err, agent))); } _onError(err, agent) { if (this._debug) { console.log(`> [debug] agent connection error ${err}\n${err.stack}`); } if (this._agent === agent) { this._agent = null; } } fetch(path, opts = {}) { if (!this._agent) { if (this._debug) { console.log("> [debug] re-initializing agent"); } this._initAgent(); } const { body } = opts; if (this._agent) { opts.agent = this._agent; } if (body && typeof body === "object" && typeof body.pipe !== "function") { opts.headers["Content-Type"] = "application/json"; opts.body = JSON.stringify(body); } if (opts.body && typeof body.pipe !== "function") { opts.headers["Content-Length"] = Buffer.byteLength(opts.body); } return fetch(this._url + path, opts); } close() { if (this._debug) { console.log("> [debug] closing agent"); } if (this._agent) { this._agent.destroy(); } } };