Skip to content

Instantly share code, notes, and snippets.

@stormpython
Created January 19, 2016 01:38
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 stormpython/f9a29894f6eb12cea217 to your computer and use it in GitHub Desktop.
Save stormpython/f9a29894f6eb12cea217 to your computer and use it in GitHub Desktop.
HTTP Proxy Example using https-proxy-agent
const { fromNode: fn } = require('bluebird');
const { createWriteStream, unlinkSync } = require('fs');
const Wreck = require('wreck');
const HttpsProxyAgent = require('https-proxy-agent');
const getProgressReporter = require('../progress_reporter');
function sendRequest({ sourceUrl, timeout, proxy }) {
const maxRedirects = 11; //Because this one goes to 11.
sourceUrl = proxy ? sourceUrl.agent = new HttpsProxyAgent(proxy) : sourceUrl;
return fn(cb => {
const req = Wreck.request('GET', sourceUrl, { timeout, redirects: maxRedirects }, (err, resp) => {
if (err) {
if (err.code === 'ECONNREFUSED') {
err = new Error('ENOTFOUND');
}
return cb(err);
}
if (resp.statusCode >= 400) {
return cb(new Error('ENOTFOUND'));
}
cb(null, { req, resp });
});
});
}
function downloadResponse({ resp, targetPath, progressReporter }) {
return new Promise((resolve, reject) => {
const writeStream = createWriteStream(targetPath);
// if either stream errors, fail quickly
resp.on('error', reject);
writeStream.on('error', reject);
// report progress as we download
resp.on('data', (chunk) => {
progressReporter.progress(chunk.length);
});
// write the download to the file system
resp.pipe(writeStream);
// when the write is done, we are done
writeStream.on('finish', resolve);
});
}
function getArchiveTypeFromResponse(resp, sourceUrl) {
const contentType = (resp.headers['content-type'] || '');
switch (contentType.toLowerCase()) {
case 'application/zip': return '.zip';
case 'application/x-gzip': return '.tar.gz';
default:
//If we can't infer the archive type from the content-type header,
//fall back to checking the extension in the url
if (/\.zip$/i.test(sourceUrl)) {
return '.zip';
}
if (/\.tar\.gz$/i.test(sourceUrl)) {
return '.tar.gz';
}
break;
}
}
/*
Responsible for managing http transfers
*/
export default async function downloadUrl(logger, sourceUrl, targetPath, timeout) {
try {
const { req, resp } = await sendRequest({ sourceUrl, timeout });
try {
let totalSize = parseFloat(resp.headers['content-length']) || 0;
const progressReporter = getProgressReporter(logger);
progressReporter.init(totalSize);
await downloadResponse({ resp, targetPath, progressReporter });
progressReporter.complete();
} catch (err) {
req.abort();
throw err;
}
// all is well, return our archive type
const archiveType = getArchiveTypeFromResponse(resp, sourceUrl);
return { archiveType };
} catch (err) {
if (err.message !== 'ENOTFOUND') {
logger.error(err);
}
throw err;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment