3 * Copyright(c) 2009-2013 TJ Holowaychuk
4 * Copyright(c) 2013 Roman Shtylman
5 * Copyright(c) 2014-2015 Douglas Christopher Wilson
12 * Module dependencies.
16 var debug = require('debug')('express:router:route');
17 var flatten = require('array-flatten');
18 var Layer = require('./layer');
19 var methods = require('methods');
26 var slice = Array.prototype.slice;
27 var toString = Object.prototype.toString;
34 module.exports = Route;
37 * Initialize `Route` with the given `path`,
39 * @param {String} path
43 function Route(path) {
49 // route handlers for various http methods
54 * Determine if the route handles a given method.
58 Route.prototype._handles_method = function _handles_method(method) {
59 if (this.methods._all) {
63 var name = method.toLowerCase();
65 if (name === 'head' && !this.methods['head']) {
69 return Boolean(this.methods[name]);
73 * @return {Array} supported HTTP methods
77 Route.prototype._options = function _options() {
78 var methods = Object.keys(this.methods);
80 // append automatic head
81 if (this.methods.get && !this.methods.head) {
85 for (var i = 0; i < methods.length; i++) {
87 methods[i] = methods[i].toUpperCase();
94 * dispatch req, res into this route
98 Route.prototype.dispatch = function dispatch(req, res, done) {
100 var stack = this.stack;
101 if (stack.length === 0) {
105 var method = req.method.toLowerCase();
106 if (method === 'head' && !this.methods['head']) {
115 // signal to exit route
116 if (err && err === 'route') {
120 // signal to exit router
121 if (err && err === 'router') {
125 var layer = stack[idx++];
130 if (layer.method && layer.method !== method) {
135 layer.handle_error(err, req, res, next);
137 layer.handle_request(req, res, next);
143 * Add a handler for all HTTP verbs to this route.
145 * Behaves just like middleware and can respond or call `next`
146 * to continue processing.
148 * You can use multiple `.all` call to add multiple handlers.
150 * function check_something(req, res, next){
154 * function validate_user(req, res, next){
159 * .all(validate_user)
160 * .all(check_something)
161 * .get(function(req, res, next){
162 * res.send('hello world');
165 * @param {function} handler
166 * @return {Route} for chaining
170 Route.prototype.all = function all() {
171 var handles = flatten(slice.call(arguments));
173 for (var i = 0; i < handles.length; i++) {
174 var handle = handles[i];
176 if (typeof handle !== 'function') {
177 var type = toString.call(handle);
178 var msg = 'Route.all() requires a callback function but got a ' + type
179 throw new TypeError(msg);
182 var layer = Layer('/', {}, handle);
183 layer.method = undefined;
185 this.methods._all = true;
186 this.stack.push(layer);
192 methods.forEach(function(method){
193 Route.prototype[method] = function(){
194 var handles = flatten(slice.call(arguments));
196 for (var i = 0; i < handles.length; i++) {
197 var handle = handles[i];
199 if (typeof handle !== 'function') {
200 var type = toString.call(handle);
201 var msg = 'Route.' + method + '() requires a callback function but got a ' + type
202 throw new Error(msg);
205 debug('%s %o', method, this.path)
207 var layer = Layer('/', {}, handle);
208 layer.method = method;
210 this.methods[method] = true;
211 this.stack.push(layer);