diff options
| author | Teddy Wing | 2013-04-27 18:20:41 -0400 | 
|---|---|---|
| committer | Teddy Wing | 2013-04-27 18:20:41 -0400 | 
| commit | 4b14305623d5ddc59f435fc5e35c54c0def1d392 (patch) | |
| tree | ef780015587343a48c46a59a7ccd0263308d062a /node_modules/express/lib/router/index.js | |
| parent | 52127aee97d0d16be652d2063c9aefbbef234f43 (diff) | |
| download | Who-am-I-4b14305623d5ddc59f435fc5e35c54c0def1d392.tar.bz2 | |
Change to node/express app
Diffstat (limited to 'node_modules/express/lib/router/index.js')
| -rw-r--r-- | node_modules/express/lib/router/index.js | 273 | 
1 files changed, 273 insertions, 0 deletions
| diff --git a/node_modules/express/lib/router/index.js b/node_modules/express/lib/router/index.js new file mode 100644 index 0000000..662dc29 --- /dev/null +++ b/node_modules/express/lib/router/index.js @@ -0,0 +1,273 @@ +/** + * Module dependencies. + */ + +var Route = require('./route') +  , utils = require('../utils') +  , methods = require('methods') +  , debug = require('debug')('express:router') +  , parse = require('connect').utils.parseUrl; + +/** + * Expose `Router` constructor. + */ + +exports = module.exports = Router; + +/** + * Initialize a new `Router` with the given `options`. + * + * @param {Object} options + * @api private + */ + +function Router(options) { +  options = options || {}; +  var self = this; +  this.map = {}; +  this.params = {}; +  this._params = []; +  this.caseSensitive = options.caseSensitive; +  this.strict = options.strict; +  this.middleware = function router(req, res, next){ +    self._dispatch(req, res, next); +  }; +} + +/** + * Register a param callback `fn` for the given `name`. + * + * @param {String|Function} name + * @param {Function} fn + * @return {Router} for chaining + * @api public + */ + +Router.prototype.param = function(name, fn){ +  // param logic +  if ('function' == typeof name) { +    this._params.push(name); +    return; +  } + +  // apply param functions +  var params = this._params +    , len = params.length +    , ret; + +  for (var i = 0; i < len; ++i) { +    if (ret = params[i](name, fn)) { +      fn = ret; +    } +  } + +  // ensure we end up with a +  // middleware function +  if ('function' != typeof fn) { +    throw new Error('invalid param() call for ' + name + ', got ' + fn); +  } + +  (this.params[name] = this.params[name] || []).push(fn); +  return this; +}; + +/** + * Route dispatcher aka the route "middleware". + * + * @param {IncomingMessage} req + * @param {ServerResponse} res + * @param {Function} next + * @api private + */ + +Router.prototype._dispatch = function(req, res, next){ +  var params = this.params +    , self = this; + +  debug('dispatching %s %s (%s)', req.method, req.url, req.originalUrl); + +  // route dispatch +  (function pass(i, err){ +    var paramCallbacks +      , paramIndex = 0 +      , paramVal +      , route +      , keys +      , key; + +    // match next route +    function nextRoute(err) { +      pass(req._route_index + 1, err); +    } + +    // match route +    req.route = route = self.matchRequest(req, i); + +    // no route +    if (!route) return next(err); +    debug('matched %s %s', route.method, route.path); + +    // we have a route +    // start at param 0 +    req.params = route.params; +    keys = route.keys; +    i = 0; + +    // param callbacks +    function param(err) { +      paramIndex = 0; +      key = keys[i++]; +      paramVal = key && req.params[key.name]; +      paramCallbacks = key && params[key.name]; + +      try { +        if ('route' == err) { +          nextRoute(); +        } else if (err) { +          i = 0; +          callbacks(err); +        } else if (paramCallbacks && undefined !== paramVal) { +          paramCallback(); +        } else if (key) { +          param(); +        } else { +          i = 0; +          callbacks(); +        } +      } catch (err) { +        param(err); +      } +    }; + +    param(err); + +    // single param callbacks +    function paramCallback(err) { +      var fn = paramCallbacks[paramIndex++]; +      if (err || !fn) return param(err); +      fn(req, res, paramCallback, paramVal, key.name); +    } + +    // invoke route callbacks +    function callbacks(err) { +      var fn = route.callbacks[i++]; +      try { +        if ('route' == err) { +          nextRoute(); +        } else if (err && fn) { +          if (fn.length < 4) return callbacks(err); +          fn(err, req, res, callbacks); +        } else if (fn) { +          if (fn.length < 4) return fn(req, res, callbacks); +          callbacks(); +        } else { +          nextRoute(err); +        } +      } catch (err) { +        callbacks(err); +      } +    } +  })(0); +}; + +/** + * Attempt to match a route for `req` + * with optional starting index of `i` + * defaulting to 0. + * + * @param {IncomingMessage} req + * @param {Number} i + * @return {Route} + * @api private + */ + +Router.prototype.matchRequest = function(req, i, head){ +  var method = req.method.toLowerCase() +    , url = parse(req) +    , path = url.pathname +    , routes = this.map +    , i = i || 0 +    , route; + +  // HEAD support +  if (!head && 'head' == method) { +    route = this.matchRequest(req, i, true); +    if (route) return route; +     method = 'get'; +  } + +  // routes for this method +  if (routes = routes[method]) { + +    // matching routes +    for (var len = routes.length; i < len; ++i) { +      route = routes[i]; +      if (route.match(path)) { +        req._route_index = i; +        return route; +      } +    } +  } +}; + +/** + * Attempt to match a route for `method` + * and `url` with optional starting + * index of `i` defaulting to 0. + * + * @param {String} method + * @param {String} url + * @param {Number} i + * @return {Route} + * @api private + */ + +Router.prototype.match = function(method, url, i, head){ +  var req = { method: method, url: url }; +  return  this.matchRequest(req, i, head); +}; + +/** + * Route `method`, `path`, and one or more callbacks. + * + * @param {String} method + * @param {String} path + * @param {Function} callback... + * @return {Router} for chaining + * @api private + */ + +Router.prototype.route = function(method, path, callbacks){ +  var method = method.toLowerCase() +    , callbacks = utils.flatten([].slice.call(arguments, 2)); + +  // ensure path was given +  if (!path) throw new Error('Router#' + method + '() requires a path'); + +  // ensure all callbacks are functions +  callbacks.forEach(function(fn, i){ +    if ('function' == typeof fn) return; +    var type = {}.toString.call(fn); +    var msg = '.' + method + '() requires callback functions but got a ' + type; +    throw new Error(msg); +  }); + +  // create the route +  debug('defined %s %s', method, path); +  var route = new Route(method, path, callbacks, { +    sensitive: this.caseSensitive, +    strict: this.strict +  }); + +  // add it +  (this.map[method] = this.map[method] || []).push(route); +  return this; +}; + +methods.forEach(function(method){ +  Router.prototype[method] = function(path){ +    var args = [method].concat([].slice.call(arguments)); +    this.route.apply(this, args); +    return this; +  }; +}); | 
