source: node_modules/express/lib/router/route.js

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 4.2 KB
Line 
1/*!
2 * express
3 * Copyright(c) 2009-2013 TJ Holowaychuk
4 * Copyright(c) 2013 Roman Shtylman
5 * Copyright(c) 2014-2015 Douglas Christopher Wilson
6 * MIT Licensed
7 */
8
9'use strict';
10
11/**
12 * Module dependencies.
13 * @private
14 */
15
16var debug = require('debug')('express:router:route');
17var flatten = require('array-flatten');
18var Layer = require('./layer');
19var methods = require('methods');
20
21/**
22 * Module variables.
23 * @private
24 */
25
26var slice = Array.prototype.slice;
27var toString = Object.prototype.toString;
28
29/**
30 * Module exports.
31 * @public
32 */
33
34module.exports = Route;
35
36/**
37 * Initialize `Route` with the given `path`,
38 *
39 * @param {String} path
40 * @public
41 */
42
43function Route(path) {
44 this.path = path;
45 this.stack = [];
46
47 debug('new %o', path)
48
49 // route handlers for various http methods
50 this.methods = {};
51}
52
53/**
54 * Determine if the route handles a given method.
55 * @private
56 */
57
58Route.prototype._handles_method = function _handles_method(method) {
59 if (this.methods._all) {
60 return true;
61 }
62
63 var name = method.toLowerCase();
64
65 if (name === 'head' && !this.methods['head']) {
66 name = 'get';
67 }
68
69 return Boolean(this.methods[name]);
70};
71
72/**
73 * @return {Array} supported HTTP methods
74 * @private
75 */
76
77Route.prototype._options = function _options() {
78 var methods = Object.keys(this.methods);
79
80 // append automatic head
81 if (this.methods.get && !this.methods.head) {
82 methods.push('head');
83 }
84
85 for (var i = 0; i < methods.length; i++) {
86 // make upper case
87 methods[i] = methods[i].toUpperCase();
88 }
89
90 return methods;
91};
92
93/**
94 * dispatch req, res into this route
95 * @private
96 */
97
98Route.prototype.dispatch = function dispatch(req, res, done) {
99 var idx = 0;
100 var stack = this.stack;
101 var sync = 0
102
103 if (stack.length === 0) {
104 return done();
105 }
106
107 var method = req.method.toLowerCase();
108 if (method === 'head' && !this.methods['head']) {
109 method = 'get';
110 }
111
112 req.route = this;
113
114 next();
115
116 function next(err) {
117 // signal to exit route
118 if (err && err === 'route') {
119 return done();
120 }
121
122 // signal to exit router
123 if (err && err === 'router') {
124 return done(err)
125 }
126
127 // max sync stack
128 if (++sync > 100) {
129 return setImmediate(next, err)
130 }
131
132 var layer = stack[idx++]
133
134 // end of layers
135 if (!layer) {
136 return done(err)
137 }
138
139 if (layer.method && layer.method !== method) {
140 next(err)
141 } else if (err) {
142 layer.handle_error(err, req, res, next);
143 } else {
144 layer.handle_request(req, res, next);
145 }
146
147 sync = 0
148 }
149};
150
151/**
152 * Add a handler for all HTTP verbs to this route.
153 *
154 * Behaves just like middleware and can respond or call `next`
155 * to continue processing.
156 *
157 * You can use multiple `.all` call to add multiple handlers.
158 *
159 * function check_something(req, res, next){
160 * next();
161 * };
162 *
163 * function validate_user(req, res, next){
164 * next();
165 * };
166 *
167 * route
168 * .all(validate_user)
169 * .all(check_something)
170 * .get(function(req, res, next){
171 * res.send('hello world');
172 * });
173 *
174 * @param {function} handler
175 * @return {Route} for chaining
176 * @api public
177 */
178
179Route.prototype.all = function all() {
180 var handles = flatten(slice.call(arguments));
181
182 for (var i = 0; i < handles.length; i++) {
183 var handle = handles[i];
184
185 if (typeof handle !== 'function') {
186 var type = toString.call(handle);
187 var msg = 'Route.all() requires a callback function but got a ' + type
188 throw new TypeError(msg);
189 }
190
191 var layer = Layer('/', {}, handle);
192 layer.method = undefined;
193
194 this.methods._all = true;
195 this.stack.push(layer);
196 }
197
198 return this;
199};
200
201methods.forEach(function(method){
202 Route.prototype[method] = function(){
203 var handles = flatten(slice.call(arguments));
204
205 for (var i = 0; i < handles.length; i++) {
206 var handle = handles[i];
207
208 if (typeof handle !== 'function') {
209 var type = toString.call(handle);
210 var msg = 'Route.' + method + '() requires a callback function but got a ' + type
211 throw new Error(msg);
212 }
213
214 debug('%s %o', method, this.path)
215
216 var layer = Layer('/', {}, handle);
217 layer.method = method;
218
219 this.methods[method] = true;
220 this.stack.push(layer);
221 }
222
223 return this;
224 };
225});
Note: See TracBrowser for help on using the repository browser.