twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

layer.js (3296B)


      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 
     16 var pathRegexp = require('path-to-regexp');
     17 var debug = require('debug')('express:router:layer');
     18 
     19 /**
     20  * Module variables.
     21  * @private
     22  */
     23 
     24 var hasOwnProperty = Object.prototype.hasOwnProperty;
     25 
     26 /**
     27  * Module exports.
     28  * @public
     29  */
     30 
     31 module.exports = Layer;
     32 
     33 function Layer(path, options, fn) {
     34   if (!(this instanceof Layer)) {
     35     return new Layer(path, options, fn);
     36   }
     37 
     38   debug('new %o', 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   // set fast path flags
     48   this.regexp.fast_star = path === '*'
     49   this.regexp.fast_slash = path === '/' && opts.end === false
     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 
     62 Layer.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 
     86 Layer.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 
    110 Layer.prototype.match = function match(path) {
    111   var match
    112 
    113   if (path != null) {
    114     // fast path non-ending match for / (any path matches)
    115     if (this.regexp.fast_slash) {
    116       this.params = {}
    117       this.path = ''
    118       return true
    119     }
    120 
    121     // fast path for * (everything matched in a param)
    122     if (this.regexp.fast_star) {
    123       this.params = {'0': decode_param(path)}
    124       this.path = path
    125       return true
    126     }
    127 
    128     // match the path
    129     match = this.regexp.exec(path)
    130   }
    131 
    132   if (!match) {
    133     this.params = undefined;
    134     this.path = undefined;
    135     return false;
    136   }
    137 
    138   // store values
    139   this.params = {};
    140   this.path = match[0]
    141 
    142   var keys = this.keys;
    143   var params = this.params;
    144 
    145   for (var i = 1; i < match.length; i++) {
    146     var key = keys[i - 1];
    147     var prop = key.name;
    148     var val = decode_param(match[i])
    149 
    150     if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
    151       params[prop] = val;
    152     }
    153   }
    154 
    155   return true;
    156 };
    157 
    158 /**
    159  * Decode param value.
    160  *
    161  * @param {string} val
    162  * @return {string}
    163  * @private
    164  */
    165 
    166 function decode_param(val) {
    167   if (typeof val !== 'string' || val.length === 0) {
    168     return val;
    169   }
    170 
    171   try {
    172     return decodeURIComponent(val);
    173   } catch (err) {
    174     if (err instanceof URIError) {
    175       err.message = 'Failed to decode param \'' + val + '\'';
    176       err.status = err.statusCode = 400;
    177     }
    178 
    179     throw err;
    180   }
    181 }