var crypto = require('crypto') var Error = require('http-errors') var utils = require('./utils') var Logger = require('./logger') module.exports.validate_name = function validate_name(req, res, next, value, name) { if (value.charAt(0) === '-') { // special case in couchdb usually next('route') } else if (utils.validate_name(value)) { next() } else { next( Error[403]('invalid ' + name) ) } } module.exports.media = function media(expect) { return function(req, res, next) { if (req.headers['content-type'] !== expect) { next( Error[415]('wrong content-type, expect: ' + expect + ', got: '+req.headers['content-type']) ) } else { next() } } } module.exports.expect_json = function expect_json(req, res, next) { if (!utils.is_object(req.body)) { return next( Error[400]("can't parse incoming json") ) } next() } 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= 200 && res.statusCode < 300)) { res.header('ETag', '"' + md5sum(body) + '"') } } else { // send(null), send(204), etc. } } catch(err) { // if sinopia sends headers first, and then calls res.send() // as an error handler, we can't report error properly, // and should just close socket if (err.message.match(/set headers after they are sent/)) { if (res.socket != null) res.socket.destroy() return } else { throw err } } res.send = _send res.send(body) } var bytesout = 0 var _write = res.write res.write = function(buf) { bytesout += buf.length _write.apply(res, arguments) } function log() { var message = "@{status}, user: @{user}, req: '@{request.method} @{request.url}'" if (res._sinopia_error) { message += ', error: @{!error}' } else { message += ', bytes: @{bytes.in}/@{bytes.out}' } var _url = req.url req.url = req.originalUrl req.log.warn({ request : { method: req.method, url: req.url }, level : 35, // http user : req.remote_user.name, status : res.statusCode, error : res._sinopia_error, bytes : { in : bytesin, out : bytesout, } }, message) req.originalUrl = req.url } req.on('close', function() { log(true) }) var _end = res.end res.end = function(buf) { if (buf) bytesout += buf.length _end.apply(res, arguments) log() } next() } module.exports.allow = function(config) { return function(action) { return function(req, res, next) { if (config['allow_'+action](req.params.package, req.remote_user)) { next() } else { if (!req.remote_user.name) { if (req.remote_user.error) { var message = "can't "+action+' restricted package, ' + req.remote_user.error } else { var message = "can't "+action+" restricted package without auth, did you forget 'npm set always-auth true'?" } next( Error[403](message) ) } else { next( Error[403]('user ' + req.remote_user.name + ' not allowed to ' + action + ' it') ) } } } } }