UNPKG

@launchdarkly/node-server-sdk

Version:
138 lines 5.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const http = require("http"); const https = require("https"); const createHttpsProxyAgent = require("https-proxy-agent"); // No types for the event source. // @ts-ignore const launchdarkly_eventsource_1 = require("launchdarkly-eventsource"); const util_1 = require("util"); const zlib = require("zlib"); const NodeResponse_1 = require("./NodeResponse"); const gzip = (0, util_1.promisify)(zlib.gzip); function processTlsOptions(tlsOptions) { const options = { ca: tlsOptions.ca, cert: tlsOptions.cert, checkServerIdentity: tlsOptions.checkServerIdentity, ciphers: tlsOptions.ciphers, // Our interface says object for the pfx object. But the node // type is more strict. This is also true for the key and KeyObject. // @ts-ignore pfx: tlsOptions.pfx, // @ts-ignore key: tlsOptions.key, passphrase: tlsOptions.passphrase, rejectUnauthorized: tlsOptions.rejectUnauthorized, secureProtocol: tlsOptions.secureProtocol, servername: tlsOptions.servername, }; // Node does not take kindly to undefined keys. Object.keys(options).forEach((key) => { if (options[key] === undefined) { delete options[key]; } }); return options; } function processProxyOptions(proxyOptions, additional = {}) { var _a; const protocol = ((_a = proxyOptions.scheme) === null || _a === void 0 ? void 0 : _a.startsWith('https')) ? 'https:' : 'http'; const parsedOptions = Object.assign({ port: proxyOptions.port, host: proxyOptions.host, protocol }, additional); if (proxyOptions.auth) { parsedOptions.headers = { 'Proxy-Authorization': `Basic ${Buffer.from(proxyOptions.auth).toString('base64')}`, }; } // Node does not take kindly to undefined keys. Object.keys(parsedOptions).forEach((key) => { if (parsedOptions[key] === undefined) { delete parsedOptions[key]; } }); return createHttpsProxyAgent(parsedOptions); } function createAgent(tlsOptions, proxyOptions, logger) { var _a; if (!((_a = proxyOptions === null || proxyOptions === void 0 ? void 0 : proxyOptions.auth) === null || _a === void 0 ? void 0 : _a.startsWith('https')) && tlsOptions) { logger === null || logger === void 0 ? void 0 : logger.warn('Proxy configured with TLS options, but is not using an https auth.'); } if (tlsOptions) { const agentOptions = processTlsOptions(tlsOptions); if (proxyOptions) { return processProxyOptions(proxyOptions, agentOptions); } return new https.Agent(agentOptions); } if (proxyOptions) { return processProxyOptions(proxyOptions); } return undefined; } class NodeRequests { constructor(tlsOptions, proxyOptions, logger, enableEventCompression) { this._hasProxy = false; this._hasProxyAuth = false; this._enableBodyCompression = false; this._agent = createAgent(tlsOptions, proxyOptions, logger); this._hasProxy = !!proxyOptions; this._hasProxyAuth = !!(proxyOptions === null || proxyOptions === void 0 ? void 0 : proxyOptions.auth); this._enableBodyCompression = !!enableEventCompression; } async fetch(url, options = {}) { var _a, _b; const isSecure = url.startsWith('https://'); const impl = isSecure ? https : http; const headers = Object.assign({}, options.headers); let bodyData = options.body; // For get requests we are going to automatically support compressed responses. // Note this does not affect SSE as the event source is not using this fetch implementation. if (((_a = options.method) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'get') { headers['accept-encoding'] = 'gzip'; } // For post requests we are going to support compressed post bodies if the // enableEventCompression config setting is true and the compressBodyIfPossible // option is true. else if (this._enableBodyCompression && !!options.compressBodyIfPossible && ((_b = options.method) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === 'post' && options.body) { headers['content-encoding'] = 'gzip'; bodyData = await gzip(Buffer.from(options.body, 'utf8')); } return new Promise((resolve, reject) => { const req = impl.request(url, { timeout: options.timeout, headers, method: options.method, agent: this._agent, }, (res) => resolve(new NodeResponse_1.default(res))); if (bodyData) { req.write(bodyData); } req.on('error', (err) => { reject(err); }); req.end(); }); } createEventSource(url, eventSourceInitDict) { const expandedOptions = Object.assign(Object.assign({}, eventSourceInitDict), { agent: this._agent, tlsParams: this._tlsOptions, maxBackoffMillis: 30 * 1000, jitterRatio: 0.5 }); return new launchdarkly_eventsource_1.EventSource(url, expandedOptions); } getEventSourceCapabilities() { return { readTimeout: true, headers: true, customMethod: true, }; } usingProxy() { return this._hasProxy; } usingProxyAuth() { return this._hasProxyAuth; } } exports.default = NodeRequests; //# sourceMappingURL=NodeRequests.js.map