@lxfriday/nodejs-file-downloader
Version:
A file downloader for NodeJs
112 lines (82 loc) • 2.68 kB
JavaScript
const { http, https } = require('follow-redirects');
const { Readable } = require('stream')
function makeRequest(url, config = {}) {
let cancelPromiseReject;
let responsePromiseReject;
let request;
const responsePromise = new Promise((resolve, reject) => {
responsePromiseReject = reject;
const protocol = url.trim().startsWith('https') ? https : http;
request = protocol.request(url, config, (res) => {
resolve(res)
});
request.end()
request.on('error',(e)=>{
responsePromiseReject(e)
})
});
const timeoutPromise = new Promise((resolve, reject) => {
if (config.timeout) {
request.setTimeout(config.timeout, () => {
const customError = new Error('Request timed out')
customError.code = 'ERR_REQUEST_TIMEDOUT'
reject(customError)
});
}
});
const cancelPromise = new Promise((resolve, reject) => {
cancelPromiseReject = reject;
})
async function makeRequestIter() {
const response = await Promise.race([
responsePromise,
cancelPromise,
timeoutPromise
]);
const responseIter = response[Symbol.asyncIterator]();
const data = (async function* () {
try {
while (true) {
const item = await Promise.race([
responseIter.next(),
cancelPromise,
timeoutPromise
]);
if (item.done) {
break;
}
yield item.value;
}
} catch (error) {
abort(request._currentRequest);
throw error
}
})();
return {
dataStream: Readable.from(data),
originalResponse: response, // The original
};
}
return {
makeRequestIter,
cancel() {
const customError = new Error('Request cancelled')
customError.code = 'ERR_REQUEST_CANCELLED'
cancelPromiseReject(customError)
}
}
}
module.exports = makeRequest;
/**
*
* @param {ClientRequest} request
*/
function abort(request) {
const majorNodeVersion = process.versions.node.split('.')[0];
// debugger
if (!majorNodeVersion || majorNodeVersion < 14) {
request.abort()
} else {
request.destroy()
}
}