raspberryGPIOhtmlserver/node_modules/express/lib/router/index.js
node_modules/express/lib/router/index.jsRaw
1/**
2 * Module dependencies.
3 */
4
5var Route = require('./route')
6 , utils = require('../utils')
7 , methods = require('methods')
8 , debug = require('debug')('express:router')
9 , parse = require('connect').utils.parseUrl;
10
11/**
12 * Expose `Router` constructor.
13 */
14
15exports = module.exports = Router;
16
17/**
18 * Initialize a new `Router` with the given `options`.
19 *
20 * @param {Object} options
21 * @api private
22 */
23
24function Router(options) {
25 options = options || {};
26 var self = this;
27 this.map = {};
28 this.params = {};
29 this._params = [];
30 this.caseSensitive = options.caseSensitive;
31 this.strict = options.strict;
32 this.middleware = function router(req, res, next){
33 self._dispatch(req, res, next);
34 };
35}
36
37/**
38 * Register a param callback `fn` for the given `name`.
39 *
40 * @param {String|Function} name
41 * @param {Function} fn
42 * @return {Router} for chaining
43 * @api public
44 */
45
46Router.prototype.param = function(name, fn){
47 // param logic
48 if ('function' == typeof name) {
49 this._params.push(name);
50 return;
51 }
52
53 // apply param functions
54 var params = this._params
55 , len = params.length
56 , ret;
57
58 for (var i = 0; i < len; ++i) {
59 if (ret = params[i](name, fn)) {
60 fn = ret;
61 }
62 }
63
64 // ensure we end up with a
65 // middleware function
66 if ('function' != typeof fn) {
67 throw new Error('invalid param() call for ' + name + ', got ' + fn);
68 }
69
70 (this.params[name] = this.params[name] || []).push(fn);
71 return this;
72};
73
74/**
75 * Route dispatcher aka the route "middleware".
76 *
77 * @param {IncomingMessage} req
78 * @param {ServerResponse} res
79 * @param {Function} next
80 * @api private
81 */
82
83Router.prototype._dispatch = function(req, res, next){
84 var params = this.params
85 , self = this;
86
87 debug('dispatching %s %s (%s)', req.method, req.url, req.originalUrl);
88
89 // route dispatch
90 (function pass(i, err){
91 var paramCallbacks
92 , paramIndex = 0
93 , paramVal
94 , route
95 , keys
96 , key;
97
98 // match next route
99 function nextRoute(err) {
100 pass(req._route_index + 1, err);
101 }
102
103 // match route
104 req.route = route = self.matchRequest(req, i);
105
106 // no route
107 if (!route) return next(err);
108 debug('matched %s %s', route.method, route.path);
109
110 // we have a route
111 // start at param 0
112 req.params = route.params;
113 keys = route.keys;
114 i = 0;
115
116 // param callbacks
117 function param(err) {
118 paramIndex = 0;
119 key = keys[i++];
120 paramVal = key && req.params[key.name];
121 paramCallbacks = key && params[key.name];
122
123 try {
124 if ('route' == err) {
125 nextRoute();
126 } else if (err) {
127 i = 0;
128 callbacks(err);
129 } else if (paramCallbacks && undefined !== paramVal) {
130 paramCallback();
131 } else if (key) {
132 param();
133 } else {
134 i = 0;
135 callbacks();
136 }
137 } catch (err) {
138 param(err);
139 }
140 };
141
142 param(err);
143
144 // single param callbacks
145 function paramCallback(err) {
146 var fn = paramCallbacks[paramIndex++];
147 if (err || !fn) return param(err);
148 fn(req, res, paramCallback, paramVal, key.name);
149 }
150
151 // invoke route callbacks
152 function callbacks(err) {
153 var fn = route.callbacks[i++];
154 try {
155 if ('route' == err) {
156 nextRoute();
157 } else if (err && fn) {
158 if (fn.length < 4) return callbacks(err);
159 fn(err, req, res, callbacks);
160 } else if (fn) {
161 if (fn.length < 4) return fn(req, res, callbacks);
162 callbacks();
163 } else {
164 nextRoute(err);
165 }
166 } catch (err) {
167 callbacks(err);
168 }
169 }
170 })(0);
171};
172
173/**
174 * Attempt to match a route for `req`
175 * with optional starting index of `i`
176 * defaulting to 0.
177 *
178 * @param {IncomingMessage} req
179 * @param {Number} i
180 * @return {Route}
181 * @api private
182 */
183
184Router.prototype.matchRequest = function(req, i, head){
185 var method = req.method.toLowerCase()
186 , url = parse(req)
187 , path = url.pathname
188 , routes = this.map
189 , i = i || 0
190 , route;
191
192 // HEAD support
193 if (!head && 'head' == method) {
194 route = this.matchRequest(req, i, true);
195 if (route) return route;
196 method = 'get';
197 }
198
199 // routes for this method
200 if (routes = routes[method]) {
201
202 // matching routes
203 for (var len = routes.length; i < len; ++i) {
204 route = routes[i];
205 if (route.match(path)) {
206 req._route_index = i;
207 return route;
208 }
209 }
210 }
211};
212
213/**
214 * Attempt to match a route for `method`
215 * and `url` with optional starting
216 * index of `i` defaulting to 0.
217 *
218 * @param {String} method
219 * @param {String} url
220 * @param {Number} i
221 * @return {Route}
222 * @api private
223 */
224
225Router.prototype.match = function(method, url, i, head){
226 var req = { method: method, url: url };
227 return this.matchRequest(req, i, head);
228};
229
230/**
231 * Route `method`, `path`, and one or more callbacks.
232 *
233 * @param {String} method
234 * @param {String} path
235 * @param {Function} callback...
236 * @return {Router} for chaining
237 * @api private
238 */
239
240Router.prototype.route = function(method, path, callbacks){
241 var method = method.toLowerCase()
242 , callbacks = utils.flatten([].slice.call(arguments, 2));
243
244 // ensure path was given
245 if (!path) throw new Error('Router#' + method + '() requires a path');
246
247 // ensure all callbacks are functions
248 callbacks.forEach(function(fn, i){
249 if ('function' == typeof fn) return;
250 var type = {}.toString.call(fn);
251 var msg = '.' + method + '() requires callback functions but got a ' + type;
252 throw new Error(msg);
253 });
254
255 // create the route
256 debug('defined %s %s', method, path);
257 var route = new Route(method, path, callbacks, {
258 sensitive: this.caseSensitive,
259 strict: this.strict
260 });
261
262 // add it
263 (this.map[method] = this.map[method] || []).push(route);
264 return this;
265};
266
267methods.forEach(function(method){
268 Router.prototype[method] = function(path){
269 var args = [method].concat([].slice.call(arguments));
270 this.route.apply(this, args);
271 return this;
272 };
273});