'use strict'; const http = require('http'); const https = require('https'); const {HttpClient, HttpClientResponse} = require('./HttpClient'); const defaultHttpAgent = new http.Agent({keepAlive: true}); const defaultHttpsAgent = new https.Agent({keepAlive: true}); /** * HTTP client which uses the Node `http` and `https` packages to issue * requests.` */ class NodeHttpClient extends HttpClient { constructor(agent) { super(); this._agent = agent; } /** @override. */ getClientName() { return 'node'; } makeRequest( host, port, path, method, headers, requestData, protocol, timeout ) { const isInsecureConnection = protocol === 'http'; let agent = this._agent; if (!agent) { agent = isInsecureConnection ? defaultHttpAgent : defaultHttpsAgent; } const requestPromise = new Promise((resolve, reject) => { const req = (isInsecureConnection ? http : https).request({ host: host, port: port, path, method, agent, headers, ciphers: 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:!MD5', }); req.setTimeout(timeout, () => { req.destroy(HttpClient.makeTimeoutError()); }); req.on('response', (res) => { resolve(new NodeHttpClientResponse(res)); }); req.on('error', (error) => { reject(error); }); req.once('socket', (socket) => { if (socket.connecting) { socket.once( isInsecureConnection ? 'connect' : 'secureConnect', () => { // Send payload; we're safe: req.write(requestData); req.end(); } ); } else { // we're already connected req.write(requestData); req.end(); } }); }); return requestPromise; } } class NodeHttpClientResponse extends HttpClientResponse { constructor(res) { super(res.statusCode, res.headers || {}); this._res = res; } getRawResponse() { return this._res; } toStream(streamCompleteCallback) { // The raw response is itself the stream, so we just return that. To be // backwards compatible, we should invoke the streamCompleteCallback only // once the stream has been fully consumed. this._res.once('end', () => streamCompleteCallback()); return this._res; } toJSON() { return new Promise((resolve, reject) => { let response = ''; this._res.setEncoding('utf8'); this._res.on('data', (chunk) => { response += chunk; }); this._res.once('end', () => { try { resolve(JSON.parse(response)); } catch (e) { reject(e); } }); }); } } module.exports = {NodeHttpClient, NodeHttpClientResponse};