UNPKG

pwabuilder-lib

Version:
94 lines (72 loc) 3.01 kB
'use strict'; 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;