//Brannon Vann Custom Request Module 1.0.1
const http = require('http');
const https = require('https');
const util = require('util');
const URL = require('url');
const tls = require('tls');
/**
* A request function to make http requests. Returns a promise that resolved to a string bod response or json if the response header content-type is json. The response may be modified using the transform option.
*
* Example Usage
* (async () => {
* const json = await request({
* uri: 'http://192.168.2.123/api/something',
* method: 'POST',
* json: { name: 'POST TEST' }
* });
* console.log(json);
* })();
*
* @param {Object} options object to make request. Supported keys: uri, method, headers, auth, json, transform.
*
* uri: The URI for the request.
* method: default is 'GET' but other standard https methods are supported (all caps)
* auth: {user: "", pass: ""}
* headers: {name: value} headers may be set with this.
* json: any data for requests for methods like post.
* transform: a function in the form of (data, body)=> {} to transform the retruned response. Otherwise the data is returned.
*
*
* @returns {Promise}
*/
async function request(options = {}) {
const { uri, method = 'GET', headers = {}, auth, json, transform, form, proxy } = options;
const agent = proxy ? new ProxyAgent(proxy) : undefined;
let query = '';
if (form) {
if (!uri.includes('?')) {
query += '?';
}
if (form && typeof form === 'object') {
for (const key in form) {
if (form.hasOwnProperty(key)) {
query += encodeURI(`&${key}=${form[key]}`);
}
}
}
}
const _options = URL.parse(uri + query);
_options.method = method;
_options.headers = headers;
_options.agent = agent;
if (auth) {
const { user, pass } = auth;
_options.headers.Authorization = `Basic ${Buffer.from(user + ':' + pass).toString('base64')}`;
}
if (json) {
_options.headers['content-type'] = 'application/json';
_options.data = JSON.stringify(json);
}
if (_options.data) _options.headers['Content-Length'] = Buffer.byteLength(_options.data);
const makeRequest = (options, callback) => {
const library = options.protocol === 'http:' ? http : https;
const req = library
.request(options, res => {
const { statusCode } = res;
let data = '';
res.on('data', chunk => {
data += chunk;
});
res.on('end', () => {
if (!statusCode || !statusCode.toString().startsWith('2')) {
const err = new Error(data);
err.statusCode = statusCode;
err.data = data;
err.options = options;
callback(err);
}
if (
statusCode !== 204 &&
res.headers['content-type'] &&
res.headers['content-type'].includes('application/json')
)
data = JSON.parse(data);
if (transform) {
const transformed = transform(data, res);
return callback(null, transformed);
} else {
return callback(null, data);
}
});
})
.on('error', err => {
err.options = options;
callback(err);
});
if (options.data) req.write(options.data);
req.end();
};
return await util.promisify(makeRequest)(_options);
}
function ProxyAgent(options) {
https.Agent.call(this, options);
//proxy options
const { host, port } = options;
this.createConnection = function (opts, callback) {
const req = http.request({
host,
port,
method: 'CONNECT',
path: opts.host + ':' + opts.port,
headers: {
host: opts.host,
},
});
req.on('connect', function (res, socket, head) {
const cts = tls.connect(
{
host: opts.host,
socket: socket,
},
function () {
callback(false, cts);
}
);
});
req.on('error', function (err) {
callback(err, null);
});
req.end();
};
}
util.inherits(ProxyAgent, https.Agent);
ProxyAgent.prototype.addRequest = function (req, options) {
let name = options.host + ':' + options.port;
if (options.path) name += ':' + options.path;
if (!this.sockets[name]) this.sockets[name] = [];
if (this.sockets[name].length < this.maxSockets) {
this.createSocket(name, options.host, options.port, options.path, req, function (socket) {
req.onSocket(socket);
});
} else {
if (!this.requests[name]) this.requests[name] = [];
this.requests[name].push(req);
}
};
ProxyAgent.prototype.createSocket = function (name, host, port, localAddress, req, callback) {
const self = this;
const options = util._extend({}, self.options);
options.port = port;
options.host = host;
options.localAddress = localAddress;
options.servername = host;
if (req) {
const hostHeader = req.getHeader('host');
if (hostHeader) options.servername = hostHeader.replace(/:.*$/, '');
}
self.createConnection(options, function (err, s) {
if (err) {
err.message += ' while connecting to the proxy server ' + self.host + ':' + self.port;
if (req) req.emit('error', err);
else throw err;
return;
}
if (!self.sockets[name]) self.sockets[name] = [];
self.sockets[name].push(s);
const onFree = function () {
self.emit('free', s, host, port, localAddress);
};
const onClose = function (err) {
self.removeSocket(s, name, host, port, localAddress);
};
const onRemove = function () {
self.removeSocket(s, name, host, port, localAddress);
s.removeListener('close', onClose);
s.removeListener('free', onFree);
s.removeListener('agentRemove', onRemove);
};
s.on('free', onFree);
s.on('close', onClose);
s.on('agentRemove', onRemove);
callback(s);
});
};
module.exports = request;
Source