pwabuilder-lib
Version:
PWA Builder Core Library
94 lines (72 loc) • 3.01 kB
JavaScript
var fs = require('fs'),
http = require('http'),
https = require('https'),
url = require('url'),
path = require('path');
var Q = require('q');
function download (inputUri, outputFilePath, callback) {
var uri = url.parse(inputUri);
if (inputUri.indexOf('http://') !== 0 && inputUri.indexOf('https://') !== 0) {
if (inputUri.indexOf(uri.protocol + '//') !== 0) {
inputUri = 'http://' + inputUri;
uri = url.parse(inputUri);
}
}
if (!(uri.protocol === 'http:' || uri.protocol === 'https:')) {
return Q.reject(new Error('Invalid protocol. Only http & https are supported.')).nodeify(callback);
}
var downloadDir = path.dirname(outputFilePath);
if (!fs.existsSync(downloadDir)) {
return Q.reject(new Error('Invalid download directory \'' + downloadDir + '\'.')).nodeify(callback);
}
var lastModified;
if (fs.existsSync(outputFilePath)) {
var stats = fs.lstatSync(outputFilePath);
lastModified = new Date(stats.mtime);
}
var options = {
host: uri.hostname,
port: uri.port || (uri.protocol === 'https:' ? 443 : 80),
path: uri.path,
agent: false
};
if (lastModified) {
options.headers = {
'if-modified-since': lastModified.toUTCString()
};
}
var protocol = uri.protocol === 'https:' ? https : http;
var deferred = Q.defer();
protocol.get(options, function (res) {
if ([301, 302].indexOf(res.statusCode) > -1) {
return download(res.headers.location, outputFilePath)
.then(function (result) { deferred.resolve(result); })
.catch(function (err) { deferred.reject(err); });
}
if ([200, 304].indexOf(res.statusCode) === -1) {
var err = new Error('Error downloading \'' + inputUri + '\'. Response was \'' + res.statusCode + ' - ' + res.statusMessage + '\'.');
err.statusCode = res.statusCode;
err.statusMessage = res.statusMessage;
return deferred.reject(err);
}
if (res.statusCode === 304) {
return deferred.resolve({ 'path': outputFilePath, 'statusCode': res.statusCode, 'statusMessage': res.statusMessage, 'contentType': res.headers['content-type'] });
}
res.pipe(fs.createWriteStream(outputFilePath))
.on('close', function () {
var lastAccessed = new Date();
var lastModified = res.headers['last-modified'] ? new Date(res.headers['last-modified']) : lastAccessed;
fs.utimes(outputFilePath, lastAccessed, lastModified, function (err) {
if (err) {
return deferred.reject(err);
}
return deferred.resolve({ 'path': outputFilePath, 'statusCode': res.statusCode, 'statusMessage': res.statusMessage, 'contentType': res.headers['content-type'] });
});
});
}).on('error', function (err) {
return deferred.reject(err);
});
return deferred.promise.nodeify(callback);
}
module.exports = download;
;