| |
| |
| |
| |
| |
| |
| |
| |
| 'use strict'; |
|
|
| |
| |
| |
| |
|
|
| var debug = require('debug')('express:router:route'); |
| var flatten = require('array-flatten'); |
| var Layer = require('./layer'); |
| var methods = require('methods'); |
|
|
| |
| |
| |
| |
|
|
| var slice = Array.prototype.slice; |
| var toString = Object.prototype.toString; |
|
|
| |
| |
| |
| |
|
|
| module.exports = Route; |
|
|
| |
| |
| |
| |
| |
| |
|
|
| function Route(path) { |
| this.path = path; |
| this.stack = []; |
|
|
| debug('new %o', path) |
|
|
| |
| this.methods = {}; |
| } |
|
|
| |
| |
| |
| |
|
|
| Route.prototype._handles_method = function _handles_method(method) { |
| if (this.methods._all) { |
| return true; |
| } |
|
|
| |
| var name = typeof method === 'string' |
| ? method.toLowerCase() |
| : method |
|
|
| if (name === 'head' && !this.methods['head']) { |
| name = 'get'; |
| } |
|
|
| return Boolean(this.methods[name]); |
| }; |
|
|
| |
| |
| |
| |
|
|
| Route.prototype._options = function _options() { |
| var methods = Object.keys(this.methods); |
|
|
| |
| if (this.methods.get && !this.methods.head) { |
| methods.push('head'); |
| } |
|
|
| for (var i = 0; i < methods.length; i++) { |
| |
| methods[i] = methods[i].toUpperCase(); |
| } |
|
|
| return methods; |
| }; |
|
|
| |
| |
| |
| |
|
|
| 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 = typeof req.method === 'string' |
| ? req.method.toLowerCase() |
| : req.method |
|
|
| if (method === 'head' && !this.methods['head']) { |
| method = 'get'; |
| } |
|
|
| req.route = this; |
|
|
| next(); |
|
|
| function next(err) { |
| |
| if (err && err === 'route') { |
| return done(); |
| } |
|
|
| |
| if (err && err === 'router') { |
| return done(err) |
| } |
|
|
| |
| if (++sync > 100) { |
| return setImmediate(next, err) |
| } |
|
|
| var layer = stack[idx++] |
|
|
| |
| 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 |
| } |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| 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; |
| }; |
| }); |
|
|