From 4d70d8065e35e28ff397e17ae1c9abfb0883b61f Mon Sep 17 00:00:00 2001 From: Alex Kocharin Date: Mon, 9 Dec 2013 07:58:25 +0400 Subject: [PATCH] add via tag to prevent loops --- lib/index.js | 2 +- lib/local-storage.js | 4 +++- lib/storage.js | 12 +++++++----- lib/up-storage.js | 46 +++++++++++++++++++++++++++++++++++--------- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/lib/index.js b/lib/index.js index b89443ba6..0bc63fd24 100644 --- a/lib/index.js +++ b/lib/index.js @@ -101,7 +101,7 @@ module.exports = function(config_hash) { // TODO: anonymous user? app.get('/:package/:version?', can('access'), function(req, res, next) { - storage.get_package(req.params.package, function(err, info) { + storage.get_package(req.params.package, {req: req}, function(err, info) { if (err) return next(err) info = utils.filter_tarball_urls(info, req, config) diff --git a/lib/local-storage.js b/lib/local-storage.js index 1f3be6bd9..08b5955cb 100644 --- a/lib/local-storage.js +++ b/lib/local-storage.js @@ -371,7 +371,9 @@ Storage.prototype.get_tarball = function(name, filename, callback) { return stream } -Storage.prototype.get_package = function(name, callback) { +Storage.prototype.get_package = function(name, options, callback) { + if (typeof(options) === 'function') callback = options, options = {} + var self = this , file = name + '/' + info_file diff --git a/lib/storage.js b/lib/storage.js index 0af05ceba..604f55633 100644 --- a/lib/storage.js +++ b/lib/storage.js @@ -385,13 +385,15 @@ Storage.prototype.get_tarball = function(name, filename) { // // Used storages: local && uplink (proxy_access) // -Storage.prototype.get_package = function(name, callback) { +Storage.prototype.get_package = function(name, options, callback) { + if (typeof(options) === 'function') callback = options, options = {} + // NOTE: callback(err, result, _uplink_errors) // _uplink_errors is an array of errors used internally // XXX: move it to another function maybe? var self = this - self.local.get_package(name, function(err, data) { + self.local.get_package(name, options, function(err, data) { if (err && (!err.status || err.status >= 500)) { // report internal errors right away return cb(err) @@ -414,11 +416,11 @@ Storage.prototype.get_package = function(name, callback) { var latest = result['dist-tags'].latest async.map(uplinks, function(up, cb) { - var oldetag = null + var _options = Object.create(options) if (utils.is_object(result._uplinks[up.upname])) - oldetag = result._uplinks[up.upname].etag + _options.etag = result._uplinks[up.upname].etag - up.get_package(name, oldetag, function(err, up_res, etag) { + up.get_package(name, _options, function(err, up_res, etag) { if (err || !up_res) return cb(null, [err || new Error('no data')]) try { diff --git a/lib/up-storage.js b/lib/up-storage.js index 33c158895..150cae5ed 100644 --- a/lib/up-storage.js +++ b/lib/up-storage.js @@ -181,7 +181,9 @@ Storage.prototype.can_fetch_url = function(url) { && url.path.indexOf(this.url.path) === 0 } -Storage.prototype.add_package = function(name, metadata, callback) { +Storage.prototype.add_package = function(name, metadata, options, callback) { + if (typeof(options) === 'function') callback = options, options = {} + this.request({ uri: '/' + escape(name), method: 'PUT', @@ -195,7 +197,9 @@ Storage.prototype.add_package = function(name, metadata, callback) { }) } -Storage.prototype.add_version = function(name, version, metadata, tag, callback) { +Storage.prototype.add_version = function(name, version, metadata, tag, options, callback) { + if (typeof(options) === 'function') callback = options, options = {} + this.request({ uri: '/' + escape(name) + '/' + escape(version) + '/-tag/' + escape(tag), method: 'PUT', @@ -209,7 +213,9 @@ Storage.prototype.add_version = function(name, version, metadata, tag, callback) }) } -Storage.prototype.add_tarball = function(name, filename) { +Storage.prototype.add_tarball = function(name, filename, options) { + if (!options) options = {} + var stream = new mystreams.UploadTarballStream() , self = this @@ -248,12 +254,15 @@ Storage.prototype.add_tarball = function(name, filename) { return stream } -Storage.prototype.get_package = function(name, etag, callback) { - if (etag) { - var headers = { - 'if-none-match': etag - } +Storage.prototype.get_package = function(name, options, callback) { + if (typeof(options) === 'function') callback = options, options = {} + + var headers = {} + if (options.etag) { + headers['If-None-Match'] = options.etag } + this._add_proxy_headers(options.req, headers) + this.request({ uri: '/' + escape(name), json: true, @@ -273,7 +282,8 @@ Storage.prototype.get_package = function(name, etag, callback) { }) } -Storage.prototype.get_tarball = function(name, filename) { +Storage.prototype.get_tarball = function(name, options, filename) { + if (!options) options = {} return this.get_url(this.config.url + '/' + name + '/-/' + filename) } @@ -309,5 +319,23 @@ Storage.prototype.get_url = function(url) { return stream } +Storage.prototype._add_proxy_headers = function(req, headers) { + if (req) { + headers['X-Forwarded-For'] = ( + (req && req.headers['x-forwarded-for']) ? + req.headers['x-forwarded-for'] + ', ' : + '' + ) + req.connection.remoteAddress + } + + // always attach Via header to avoid loops, even if we're not proxying + headers['Via'] = + (req && req.headers['via']) ? + req.headers['via'] + ', ' : + '' + + headers['Via'] += '1.1 ' + this.server_id + ' (Sinopia)' +} + module.exports = Storage