Spaces:
Runtime error
Runtime error
/*! | |
* express | |
* Copyright(c) 2009-2013 TJ Holowaychuk | |
* Copyright(c) 2013 Roman Shtylman | |
* Copyright(c) 2014-2015 Douglas Christopher Wilson | |
* MIT Licensed | |
*/ | |
; | |
/** | |
* Module dependencies. | |
* @private | |
*/ | |
var debug = require('debug')('express:router:route'); | |
var flatten = require('array-flatten'); | |
var Layer = require('./layer'); | |
var methods = require('methods'); | |
/** | |
* Module variables. | |
* @private | |
*/ | |
var slice = Array.prototype.slice; | |
var toString = Object.prototype.toString; | |
/** | |
* Module exports. | |
* @public | |
*/ | |
module.exports = Route; | |
/** | |
* Initialize `Route` with the given `path`, | |
* | |
* @param {String} path | |
* @public | |
*/ | |
function Route(path) { | |
this.path = path; | |
this.stack = []; | |
debug('new %o', path) | |
// route handlers for various http methods | |
this.methods = {}; | |
} | |
/** | |
* Determine if the route handles a given method. | |
* @private | |
*/ | |
Route.prototype._handles_method = function _handles_method(method) { | |
if (this.methods._all) { | |
return true; | |
} | |
var name = method.toLowerCase(); | |
if (name === 'head' && !this.methods['head']) { | |
name = 'get'; | |
} | |
return Boolean(this.methods[name]); | |
}; | |
/** | |
* @return {Array} supported HTTP methods | |
* @private | |
*/ | |
Route.prototype._options = function _options() { | |
var methods = Object.keys(this.methods); | |
// append automatic head | |
if (this.methods.get && !this.methods.head) { | |
methods.push('head'); | |
} | |
for (var i = 0; i < methods.length; i++) { | |
// make upper case | |
methods[i] = methods[i].toUpperCase(); | |
} | |
return methods; | |
}; | |
/** | |
* dispatch req, res into this route | |
* @private | |
*/ | |
Route.prototype.dispatch = function dispatch(req, res, done) { | |
var idx = 0; | |
var stack = this.stack; | |
var sync = 0 | |
if (stack.length === 0) { | |
return done(); | |
} | |
var method = req.method.toLowerCase(); | |
if (method === 'head' && !this.methods['head']) { | |
method = 'get'; | |
} | |
req.route = this; | |
next(); | |
function next(err) { | |
// signal to exit route | |
if (err && err === 'route') { | |
return done(); | |
} | |
// signal to exit router | |
if (err && err === 'router') { | |
return done(err) | |
} | |
// max sync stack | |
if (++sync > 100) { | |
return setImmediate(next, err) | |
} | |
var layer = stack[idx++] | |
// end of layers | |
if (!layer) { | |
return done(err) | |
} | |
if (layer.method && layer.method !== method) { | |
next(err) | |
} else if (err) { | |
layer.handle_error(err, req, res, next); | |
} else { | |
layer.handle_request(req, res, next); | |
} | |
sync = 0 | |
} | |
}; | |
/** | |
* Add a handler for all HTTP verbs to this route. | |
* | |
* Behaves just like middleware and can respond or call `next` | |
* to continue processing. | |
* | |
* You can use multiple `.all` call to add multiple handlers. | |
* | |
* function check_something(req, res, next){ | |
* next(); | |
* }; | |
* | |
* function validate_user(req, res, next){ | |
* next(); | |
* }; | |
* | |
* route | |
* .all(validate_user) | |
* .all(check_something) | |
* .get(function(req, res, next){ | |
* res.send('hello world'); | |
* }); | |
* | |
* @param {function} handler | |
* @return {Route} for chaining | |
* @api public | |
*/ | |
Route.prototype.all = function all() { | |
var handles = flatten(slice.call(arguments)); | |
for (var i = 0; i < handles.length; i++) { | |
var handle = handles[i]; | |
if (typeof handle !== 'function') { | |
var type = toString.call(handle); | |
var msg = 'Route.all() requires a callback function but got a ' + type | |
throw new TypeError(msg); | |
} | |
var layer = Layer('/', {}, handle); | |
layer.method = undefined; | |
this.methods._all = true; | |
this.stack.push(layer); | |
} | |
return this; | |
}; | |
methods.forEach(function(method){ | |
Route.prototype[method] = function(){ | |
var handles = flatten(slice.call(arguments)); | |
for (var i = 0; i < handles.length; i++) { | |
var handle = handles[i]; | |
if (typeof handle !== 'function') { | |
var type = toString.call(handle); | |
var msg = 'Route.' + method + '() requires a callback function but got a ' + type | |
throw new Error(msg); | |
} | |
debug('%s %o', method, this.path) | |
var layer = Layer('/', {}, handle); | |
layer.method = method; | |
this.methods[method] = true; | |
this.stack.push(layer); | |
} | |
return this; | |
}; | |
}); | |