detecting http loops

This commit is contained in:
Alex Kocharin 2013-12-09 07:59:31 +04:00
parent 4d70d8065e
commit bbb402f762
5 changed files with 34 additions and 1 deletions

View File

@ -104,6 +104,11 @@ function Config(config) {
}
}).bind(this))
// unique identifier of this server (or a cluster), used to avoid loops
if (!this.server_id) {
this.server_id = crypto.pseudoRandomBytes(6).toString('hex')
}
return this
}

View File

@ -76,6 +76,7 @@ module.exports = function(config_hash) {
// TODO: npm DO NOT support compression :(
app.use(express.compress())
app.use(Middleware.anti_loop(config))
app.param('package', validate_name)
app.param('filename', validate_name)

View File

@ -84,6 +84,24 @@ module.exports.basic_auth = function basic_auth(callback) {
}
}
module.exports.anti_loop = function(config) {
return function(req, res, next) {
if (req.headers.via != null) {
var arr = req.headers.via.split(',')
for (var i=0; i<arr.length; i++) {
var m = arr[i].match(/\s*(\S+)\s+(\S+)/)
if (m && m[2] === config.server_id) {
return next(new UError({
status: 508,
msg: 'loop detected',
}))
}
}
}
next()
}
}
// express doesn't do etags with requests <= 1024b
// we use md5 here, it works well on 1k+ bytes, but sucks with fewer data
// could improve performance using crc32 after benchmarks

View File

@ -16,6 +16,7 @@ function Storage(config, mainconfig) {
this.userAgent = mainconfig.user_agent
this.ca = config.ca
this.logger = Logger.logger.child({sub: 'out'})
this.server_id = mainconfig.server_id
this.url = URL.parse(this.config.url)
if (this.url.hostname === 'registry.npmjs.org') {

View File

@ -4,7 +4,15 @@ var ex = module.exports;
var server = process.server;
var server2 = process.server2;
['fwd'/*, 'loop'*/].forEach(function(pkg) {
ex['testing anti-loop'] = function(cb) {
server2.get_package('testloop', function(res, body) {
assert.equal(res.statusCode, 404);
assert(~body.error.indexOf('no such package'));
cb();
});
};
['fwd', 'loop'].forEach(function(pkg) {
var prefix = pkg+': ';
pkg = 'test'+pkg;