arnaucube
arnaucube/thoughtsPublic Self-hosted repository
thoughts/node_modules/express/lib/router/route.js
node_modules/express/lib/router/route.jsRaw
  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 %s', 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  if (stack.length === 0) {
102    return done();
103  }
104
105  var method = req.method.toLowerCase();
106  if (method === 'head' && !this.methods['head']) {
107    method = 'get';
108  }
109
110  req.route = this;
111
112  next();
113
114  function next(err) {
115    if (err && err === 'route') {
116      return done();
117    }
118
119    var layer = stack[idx++];
120    if (!layer) {
121      return done(err);
122    }
123
124    if (layer.method && layer.method !== method) {
125      return next(err);
126    }
127
128    if (err) {
129      layer.handle_error(err, req, res, next);
130    } else {
131      layer.handle_request(req, res, next);
132    }
133  }
134};
135
136/**
137 * Add a handler for all HTTP verbs to this route.
138 *
139 * Behaves just like middleware and can respond or call `next`
140 * to continue processing.
141 *
142 * You can use multiple `.all` call to add multiple handlers.
143 *
144 *   function check_something(req, res, next){
145 *     next();
146 *   };
147 *
148 *   function validate_user(req, res, next){
149 *     next();
150 *   };
151 *
152 *   route
153 *   .all(validate_user)
154 *   .all(check_something)
155 *   .get(function(req, res, next){
156 *     res.send('hello world');
157 *   });
158 *
159 * @param {function} handler
160 * @return {Route} for chaining
161 * @api public
162 */
163
164Route.prototype.all = function all() {
165  var handles = flatten(slice.call(arguments));
166
167  for (var i = 0; i < handles.length; i++) {
168    var handle = handles[i];
169
170    if (typeof handle !== 'function') {
171      var type = toString.call(handle);
172      var msg = 'Route.all() requires callback functions but got a ' + type;
173      throw new TypeError(msg);
174    }
175
176    var layer = Layer('/', {}, handle);
177    layer.method = undefined;
178
179    this.methods._all = true;
180    this.stack.push(layer);
181  }
182
183  return this;
184};
185
186methods.forEach(function(method){
187  Route.prototype[method] = function(){
188    var handles = flatten(slice.call(arguments));
189
190    for (var i = 0; i < handles.length; i++) {
191      var handle = handles[i];
192
193      if (typeof handle !== 'function') {
194        var type = toString.call(handle);
195        var msg = 'Route.' + method + '() requires callback functions but got a ' + type;
196        throw new Error(msg);
197      }
198
199      debug('%s %s', method, this.path);
200
201      var layer = Layer('/', {}, handle);
202      layer.method = method;
203
204      this.methods[method] = true;
205      this.stack.push(layer);
206    }
207
208    return this;
209  };
210});