arnaucube
arnaucube/thoughtsPublic Self-hosted repository
thoughts/node_modules/express/lib/router/layer.js
node_modules/express/lib/router/layer.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 pathRegexp = require('path-to-regexp');
 17var debug = require('debug')('express:router:layer');
 18
 19/**
 20 * Module variables.
 21 * @private
 22 */
 23
 24var hasOwnProperty = Object.prototype.hasOwnProperty;
 25
 26/**
 27 * Module exports.
 28 * @public
 29 */
 30
 31module.exports = Layer;
 32
 33function Layer(path, options, fn) {
 34  if (!(this instanceof Layer)) {
 35    return new Layer(path, options, fn);
 36  }
 37
 38  debug('new %s', path);
 39  var opts = options || {};
 40
 41  this.handle = fn;
 42  this.name = fn.name || '<anonymous>';
 43  this.params = undefined;
 44  this.path = undefined;
 45  this.regexp = pathRegexp(path, this.keys = [], opts);
 46
 47  if (path === '/' && opts.end === false) {
 48    this.regexp.fast_slash = true;
 49  }
 50}
 51
 52/**
 53 * Handle the error for the layer.
 54 *
 55 * @param {Error} error
 56 * @param {Request} req
 57 * @param {Response} res
 58 * @param {function} next
 59 * @api private
 60 */
 61
 62Layer.prototype.handle_error = function handle_error(error, req, res, next) {
 63  var fn = this.handle;
 64
 65  if (fn.length !== 4) {
 66    // not a standard error handler
 67    return next(error);
 68  }
 69
 70  try {
 71    fn(error, req, res, next);
 72  } catch (err) {
 73    next(err);
 74  }
 75};
 76
 77/**
 78 * Handle the request for the layer.
 79 *
 80 * @param {Request} req
 81 * @param {Response} res
 82 * @param {function} next
 83 * @api private
 84 */
 85
 86Layer.prototype.handle_request = function handle(req, res, next) {
 87  var fn = this.handle;
 88
 89  if (fn.length > 3) {
 90    // not a standard request handler
 91    return next();
 92  }
 93
 94  try {
 95    fn(req, res, next);
 96  } catch (err) {
 97    next(err);
 98  }
 99};
100
101/**
102 * Check if this route matches `path`, if so
103 * populate `.params`.
104 *
105 * @param {String} path
106 * @return {Boolean}
107 * @api private
108 */
109
110Layer.prototype.match = function match(path) {
111  if (path == null) {
112    // no path, nothing matches
113    this.params = undefined;
114    this.path = undefined;
115    return false;
116  }
117
118  if (this.regexp.fast_slash) {
119    // fast path non-ending match for / (everything matches)
120    this.params = {};
121    this.path = '';
122    return true;
123  }
124
125  var m = this.regexp.exec(path);
126
127  if (!m) {
128    this.params = undefined;
129    this.path = undefined;
130    return false;
131  }
132
133  // store values
134  this.params = {};
135  this.path = m[0];
136
137  var keys = this.keys;
138  var params = this.params;
139
140  for (var i = 1; i < m.length; i++) {
141    var key = keys[i - 1];
142    var prop = key.name;
143    var val = decode_param(m[i]);
144
145    if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
146      params[prop] = val;
147    }
148  }
149
150  return true;
151};
152
153/**
154 * Decode param value.
155 *
156 * @param {string} val
157 * @return {string}
158 * @private
159 */
160
161function decode_param(val) {
162  if (typeof val !== 'string' || val.length === 0) {
163    return val;
164  }
165
166  try {
167    return decodeURIComponent(val);
168  } catch (err) {
169    if (err instanceof URIError) {
170      err.message = 'Failed to decode param \'' + val + '\'';
171      err.status = err.statusCode = 400;
172    }
173
174    throw err;
175  }
176}