diff --git a/lib/index.js b/lib/index.js index 19eb81c1..8e4ce4d6 100644 --- a/lib/index.js +++ b/lib/index.js @@ -64,15 +64,7 @@ module.exports = function(config_hash) { if (err.status && err.status >= 400 && err.status < 600) { if (calls == 1) { res.status(err.status) - var body = {error: err.msg || err.message || 'unknown error'}; - - // Make 404 responses compliant with CouchDB REST API - if (err.status == 404) { - body.reason = body.error - body.error = 'not_found' - } - - res.send(body) + res.send({error: err.msg || err.message || 'unknown error', reason: err.reason}) } } else { Logger.logger.error({err: err}, 'unexpected error: @{!err.message}\n@{err.stack}') @@ -138,7 +130,15 @@ module.exports = function(config_hash) { // TODO: anonymous user? app.get('/:package/:version?', can('access'), function(req, res, next) { storage.get_package(req.params.package, {req: req}, function(err, info) { - if (err) return next(err) + if (err) { + if (err.status == 404) { + // Make 404 responses compliant with CouchDB REST API + // Pretend the Couch document for the package was not found + err.reason = err.msg + err.msg = 'not_found' + } + return next(err) + } info = utils.filter_tarball_urls(info, req, config) var version = req.params.version diff --git a/package.yaml b/package.yaml index c99173e8..90f55a57 100644 --- a/package.yaml +++ b/package.yaml @@ -32,11 +32,14 @@ dependencies: devDependencies: rimraf: '>= 2.2.5' - mocha: '>= 1.17.0' + mocha: '>= 1.18.0' # linting tools eslint: '>= 0.4.2' + # validation suite for the npm registry protocol + 'registry-validator': '>=0.1.0' + # for debugging memory leaks, it'll be require()'d if # installed, but I don't want it to be installed everytime #heapdump: '*' @@ -51,7 +54,7 @@ keywords: - server scripts: - test: mocha ./test/functional ./test/unit + test: mocha ./test/functional ./test/unit ./test/validation lint: eslint -c ./.eslint.yaml ./lib # we depend on streams2 stuff diff --git a/test/functional/addtag.js b/test/functional/addtag.js index 08dfdff5..593f5658 100644 --- a/test/functional/addtag.js +++ b/test/functional/addtag.js @@ -10,8 +10,7 @@ module.exports = function() { it('add tag - 404', function(cb) { server.add_tag('testpkg-tag', 'tagtagtag', '0.0.1', function(res, body) { assert.equal(res.statusCode, 404) - assert.equal(body.error, 'not_found') - assert(~body.reason.indexOf('no such package')) + assert(~body.error.indexOf('no such package')) cb() }) }) @@ -35,8 +34,7 @@ module.exports = function() { it('add tag - bad ver', function(cb) { server.add_tag('testpkg-tag', 'tagtagtag', '0.0.1-x', function(res, body) { assert.equal(res.statusCode, 404) - assert.equal(body.error, 'not_found') - assert(~body.reason.indexOf('version doesn\'t exist')) + assert(~body.error.indexOf('version doesn\'t exist')) cb() }) }) diff --git a/test/functional/basic.js b/test/functional/basic.js index e2bc202a..3ad94d42 100644 --- a/test/functional/basic.js +++ b/test/functional/basic.js @@ -29,8 +29,7 @@ module.exports = function() { it('downloading non-existent tarball', function(cb) { server.get_tarball('testpkg', 'blahblah', function(res, body) { assert.equal(res.statusCode, 404) - assert.equal(body.error, 'not_found') - assert(~body.reason.indexOf('no such file')) + assert(~body.error.indexOf('no such file')) cb() }) }) @@ -111,8 +110,7 @@ module.exports = function() { it('uploading new package version for bad pkg', function(cb) { server.put_version('testpxg', '0.0.1', require('./lib/package')('testpxg'), function(res, body) { assert.equal(res.statusCode, 404) - assert.equal(body.error, 'not_found') - assert(~body.reason.indexOf('no such package')) + assert(~body.error.indexOf('no such package')) cb() }) }) diff --git a/test/functional/gh29.js b/test/functional/gh29.js index 603bc30c..3847db5d 100644 --- a/test/functional/gh29.js +++ b/test/functional/gh29.js @@ -13,8 +13,7 @@ module.exports = function() { it('downloading non-existent tarball #1 / srv2', function(cb) { server2.get_tarball('testpkg-gh29', 'blahblah', function(res, body) { assert.equal(res.statusCode, 404) - assert.equal(body.error, 'not_found') - assert(~body.reason.indexOf('no such package')) + assert(~body.error.indexOf('no such package')) cb() }) }) @@ -33,8 +32,7 @@ module.exports = function() { it('downloading non-existent tarball #2 / srv2', function(cb) { server2.get_tarball('testpkg-gh29', 'blahblah', function(res, body) { assert.equal(res.statusCode, 404) - assert.equal(body.error, 'not_found') - assert(~body.reason.indexOf('no such file')) + assert(~body.error.indexOf('no such file')) cb() }) }) diff --git a/test/validation/config.yaml b/test/validation/config.yaml new file mode 100644 index 00000000..4c59c4df --- /dev/null +++ b/test/validation/config.yaml @@ -0,0 +1,17 @@ +storage: ./test-storage + +users: + test: + password: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 + +uplinks: + +logs: + - {type: stderr, format: pretty, level: trace} + +packages: + '*': + allow_access: test all + allow_publish: test + +listen: 55555 diff --git a/test/validation/validation.js b/test/validation/validation.js new file mode 100644 index 00000000..d03060ce --- /dev/null +++ b/test/validation/validation.js @@ -0,0 +1,35 @@ +var validator = require('registry-validator') + , path = require('path') + , rimraf = require('rimraf') + , fork = require('child_process').fork; + +// the values must be synchronized with config.yaml +var STORAGE = path.resolve(__dirname, 'test-storage') + , PORT = 55555 + , AUTH = 'test:test'; + +describe('The registry protocol', function() { + var child; + + before(function(done) { + rimraf(STORAGE, function() { + child = fork(__dirname + '/../../bin/sinopia' + , ['-c', path.resolve(__dirname, 'config.yaml')] + , {silent: true}) + process.on('exit', function() { child.kill(); }); + child.on('message', function(msg) { + if (!('sinopia_started' in msg)) return; + validator.configure('http://localhost:' + PORT + '/', { + userCredentials: AUTH + }); + done() + }); + }); + }); + + after(function() { + if (child) child.kill(); + }); + + validator.defineSuite(); +});