Skip to content

Instantly share code, notes, and snippets.

@yurynix
Created March 24, 2020 08:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yurynix/f57b38d5870691aff8d479905c173c04 to your computer and use it in GitHub Desktop.
Save yurynix/f57b38d5870691aff8d479905c173c04 to your computer and use it in GitHub Desktop.
Lightweight request using native node http.request
/*
Usage example:
request({
url: tarballUrl,
headers: registry.headers,
dataHandler: dataBuffer => {
if (shasum) {
shasum.update(dataBuffer);
}
byteCount += dataBuffer.length;
},
});
*/
const http = require('http');
const https = require('https');
const url = require('url');
const REQUEST_DEFAULTS = {
method: 'GET',
headers: {},
};
const REQUEST_TIMEOUT = 60 * 1000;
function request(requestOptions) {
const parsedUrl = url.parse(requestOptions.url);
const options = {
hostname: requestOptions.ip ? requestOptions.ip : parsedUrl.hostname,
port: parsedUrl.protocol === 'https:' ? 443 : 80,
path: parsedUrl.path,
method: requestOptions.method || REQUEST_DEFAULTS.method,
headers: requestOptions.headers || REQUEST_DEFAULTS.headers,
};
if (requestOptions.ip) {
options.headers['Host'] = parsedUrl.hostname;
}
if (requestOptions.data) {
options.headers['Content-Length'] = Buffer.byteLength(requestOptions.data);
}
return new Promise((resolve, reject) => {
let requestTimer = null;
const start = process.hrtime();
let remoteAddress;
const httpAdapater = parsedUrl.protocol === 'https:' ? https : http;
const req = httpAdapater.request(options, res => {
const statusCode = res.statusCode;
remoteAddress = res.connection.remoteAddress;
const clearRequestTimer = () => {
if (requestTimer) {
clearTimeout(requestTimer);
requestTimer = null;
}
};
if (statusCode !== 200 && statusCode !== 201) {
let buf = Buffer.alloc(0);
res.on('data', dataBuffer => {
buf = Buffer.concat(
[buf, dataBuffer],
buf.length + dataBuffer.length,
);
});
res.on('end', () => {
clearRequestTimer();
reject(
new Error(
`Got HTTP status code: ${statusCode} from: ${remoteAddress} response(${
buf.length
}bytes): ${buf.toString()}`,
),
);
});
} else {
res.on('data', dataBuffer => {
if (typeof requestOptions.dataHandler === 'function') {
requestOptions.dataHandler(dataBuffer);
}
});
res.on('end', () => {
const end = process.hrtime(start);
const endTimeString = `${end[0]}s ${end[1] / 1000000}ms`;
clearRequestTimer();
resolve({
requestTime: endTimeString,
remoteAddress,
});
});
}
});
req.on('error', e => {
reject(new Error(`Error making request ${requestOptions.url}: ${e}`));
});
requestTimer = setTimeout(function request_timeout() {
req.abort();
reject(
new Error(
`Request ${
requestOptions.url
} (${remoteAddress}) timeout after ${REQUEST_TIMEOUT}ms`,
),
);
}, REQUEST_TIMEOUT);
if (requestOptions.data) {
req.write(requestOptions.data);
}
req.end();
});
}
module.exports = request;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment