/* automatically generated by JSCoverage - do not edit */
if (typeof _$jscoverage === 'undefined') _$jscoverage = {};
if (! _$jscoverage['router/index.js']) {
  _$jscoverage['router/index.js'] = [];
  _$jscoverage['router/index.js'][11] = 0;
  _$jscoverage['router/index.js'][21] = 0;
  _$jscoverage['router/index.js'][27] = 0;
  _$jscoverage['router/index.js'][36] = 0;
  _$jscoverage['router/index.js'][37] = 0;
  _$jscoverage['router/index.js'][38] = 0;
  _$jscoverage['router/index.js'][39] = 0;
  _$jscoverage['router/index.js'][40] = 0;
  _$jscoverage['router/index.js'][41] = 0;
  _$jscoverage['router/index.js'][42] = 0;
  _$jscoverage['router/index.js'][43] = 0;
  _$jscoverage['router/index.js'][44] = 0;
  _$jscoverage['router/index.js'][46] = 0;
  _$jscoverage['router/index.js'][47] = 0;
  _$jscoverage['router/index.js'][60] = 0;
  _$jscoverage['router/index.js'][62] = 0;
  _$jscoverage['router/index.js'][63] = 0;
  _$jscoverage['router/index.js'][64] = 0;
  _$jscoverage['router/index.js'][68] = 0;
  _$jscoverage['router/index.js'][72] = 0;
  _$jscoverage['router/index.js'][73] = 0;
  _$jscoverage['router/index.js'][74] = 0;
  _$jscoverage['router/index.js'][80] = 0;
  _$jscoverage['router/index.js'][81] = 0;
  _$jscoverage['router/index.js'][84] = 0;
  _$jscoverage['router/index.js'][85] = 0;
  _$jscoverage['router/index.js'][95] = 0;
  _$jscoverage['router/index.js'][96] = 0;
  _$jscoverage['router/index.js'][97] = 0;
  _$jscoverage['router/index.js'][111] = 0;
  _$jscoverage['router/index.js'][112] = 0;
  _$jscoverage['router/index.js'][116] = 0;
  _$jscoverage['router/index.js'][117] = 0;
  _$jscoverage['router/index.js'][120] = 0;
  _$jscoverage['router/index.js'][121] = 0;
  _$jscoverage['router/index.js'][122] = 0;
  _$jscoverage['router/index.js'][123] = 0;
  _$jscoverage['router/index.js'][137] = 0;
  _$jscoverage['router/index.js'][138] = 0;
  _$jscoverage['router/index.js'][139] = 0;
  _$jscoverage['router/index.js'][171] = 0;
  _$jscoverage['router/index.js'][172] = 0;
  _$jscoverage['router/index.js'][178] = 0;
  _$jscoverage['router/index.js'][179] = 0;
  _$jscoverage['router/index.js'][180] = 0;
  _$jscoverage['router/index.js'][181] = 0;
  _$jscoverage['router/index.js'][182] = 0;
  _$jscoverage['router/index.js'][183] = 0;
  _$jscoverage['router/index.js'][184] = 0;
  _$jscoverage['router/index.js'][188] = 0;
  _$jscoverage['router/index.js'][200] = 0;
  _$jscoverage['router/index.js'][201] = 0;
  _$jscoverage['router/index.js'][204] = 0;
  _$jscoverage['router/index.js'][207] = 0;
  _$jscoverage['router/index.js'][208] = 0;
  _$jscoverage['router/index.js'][217] = 0;
  _$jscoverage['router/index.js'][218] = 0;
  _$jscoverage['router/index.js'][222] = 0;
  _$jscoverage['router/index.js'][225] = 0;
  _$jscoverage['router/index.js'][228] = 0;
  _$jscoverage['router/index.js'][229] = 0;
  _$jscoverage['router/index.js'][233] = 0;
  _$jscoverage['router/index.js'][234] = 0;
  _$jscoverage['router/index.js'][235] = 0;
  _$jscoverage['router/index.js'][238] = 0;
  _$jscoverage['router/index.js'][239] = 0;
  _$jscoverage['router/index.js'][240] = 0;
  _$jscoverage['router/index.js'][241] = 0;
  _$jscoverage['router/index.js'][242] = 0;
  _$jscoverage['router/index.js'][244] = 0;
  _$jscoverage['router/index.js'][245] = 0;
  _$jscoverage['router/index.js'][246] = 0;
  _$jscoverage['router/index.js'][247] = 0;
  _$jscoverage['router/index.js'][248] = 0;
  _$jscoverage['router/index.js'][249] = 0;
  _$jscoverage['router/index.js'][250] = 0;
  _$jscoverage['router/index.js'][251] = 0;
  _$jscoverage['router/index.js'][252] = 0;
  _$jscoverage['router/index.js'][253] = 0;
  _$jscoverage['router/index.js'][255] = 0;
  _$jscoverage['router/index.js'][256] = 0;
  _$jscoverage['router/index.js'][259] = 0;
  _$jscoverage['router/index.js'][261] = 0;
  _$jscoverage['router/index.js'][263] = 0;
  _$jscoverage['router/index.js'][266] = 0;
  _$jscoverage['router/index.js'][267] = 0;
  _$jscoverage['router/index.js'][268] = 0;
  _$jscoverage['router/index.js'][269] = 0;
  _$jscoverage['router/index.js'][273] = 0;
  _$jscoverage['router/index.js'][274] = 0;
  _$jscoverage['router/index.js'][275] = 0;
  _$jscoverage['router/index.js'][276] = 0;
  _$jscoverage['router/index.js'][277] = 0;
  _$jscoverage['router/index.js'][278] = 0;
  _$jscoverage['router/index.js'][279] = 0;
  _$jscoverage['router/index.js'][280] = 0;
  _$jscoverage['router/index.js'][281] = 0;
  _$jscoverage['router/index.js'][282] = 0;
  _$jscoverage['router/index.js'][284] = 0;
  _$jscoverage['router/index.js'][287] = 0;
  _$jscoverage['router/index.js'][301] = 0;
  _$jscoverage['router/index.js'][302] = 0;
  _$jscoverage['router/index.js'][304] = 0;
  _$jscoverage['router/index.js'][315] = 0;
  _$jscoverage['router/index.js'][316] = 0;
  _$jscoverage['router/index.js'][317] = 0;
  _$jscoverage['router/index.js'][318] = 0;
  _$jscoverage['router/index.js'][319] = 0;
  _$jscoverage['router/index.js'][320] = 0;
  _$jscoverage['router/index.js'][321] = 0;
  _$jscoverage['router/index.js'][324] = 0;
  _$jscoverage['router/index.js'][339] = 0;
  _$jscoverage['router/index.js'][340] = 0;
  _$jscoverage['router/index.js'][351] = 0;
  _$jscoverage['router/index.js'][353] = 0;
  _$jscoverage['router/index.js'][354] = 0;
  _$jscoverage['router/index.js'][358] = 0;
  _$jscoverage['router/index.js'][362] = 0;
  _$jscoverage['router/index.js'][365] = 0;
  _$jscoverage['router/index.js'][366] = 0;
  _$jscoverage['router/index.js'][367] = 0;
  _$jscoverage['router/index.js'][368] = 0;
  _$jscoverage['router/index.js'][369] = 0;
  _$jscoverage['router/index.js'][372] = 0;
  _$jscoverage['router/index.js'][373] = 0;
  _$jscoverage['router/index.js'][377] = 0;
  _$jscoverage['router/index.js'][378] = 0;
  _$jscoverage['router/index.js'][380] = 0;
  _$jscoverage['router/index.js'][385] = 0;
  _$jscoverage['router/index.js'][386] = 0;
  _$jscoverage['router/index.js'][402] = 0;
  _$jscoverage['router/index.js'][403] = 0;
  _$jscoverage['router/index.js'][408] = 0;
  _$jscoverage['router/index.js'][411] = 0;
  _$jscoverage['router/index.js'][412] = 0;
  _$jscoverage['router/index.js'][418] = 0;
  _$jscoverage['router/index.js'][419] = 0;
  _$jscoverage['router/index.js'][420] = 0;
}
_$jscoverage['router/index.js'][11]++;
var Route = require("./route"), Collection = require("./collection"), utils = require("../utils"), debug = require("debug")("express:router"), parse = require("url").parse;
_$jscoverage['router/index.js'][21]++;
exports = module.exports = Router;
_$jscoverage['router/index.js'][27]++;
var methods = exports.methods = require("./methods");
_$jscoverage['router/index.js'][36]++;
function Router(options) {
  _$jscoverage['router/index.js'][37]++;
  options = options || {};
  _$jscoverage['router/index.js'][38]++;
  var self = this;
  _$jscoverage['router/index.js'][39]++;
  this.routes = new Collection();
  _$jscoverage['router/index.js'][40]++;
  this.map = {};
  _$jscoverage['router/index.js'][41]++;
  this.params = {};
  _$jscoverage['router/index.js'][42]++;
  this._params = [];
  _$jscoverage['router/index.js'][43]++;
  this.caseSensitive = options.caseSensitive;
  _$jscoverage['router/index.js'][44]++;
  this.strict = options.strict;
  _$jscoverage['router/index.js'][46]++;
  this.middleware = (function router(req, res, next) {
  _$jscoverage['router/index.js'][47]++;
  self._dispatch(req, res, next);
});
}
_$jscoverage['router/index.js'][60]++;
Router.prototype.param = (function (name, fn) {
  _$jscoverage['router/index.js'][62]++;
  if ("function" == typeof name) {
    _$jscoverage['router/index.js'][63]++;
    this._params.push(name);
    _$jscoverage['router/index.js'][64]++;
    return;
  }
  _$jscoverage['router/index.js'][68]++;
  var params = this._params, len = params.length, ret;
  _$jscoverage['router/index.js'][72]++;
  for (var i = 0; i < len; ++i) {
    _$jscoverage['router/index.js'][73]++;
    if (ret = params[i](name, fn)) {
      _$jscoverage['router/index.js'][74]++;
      fn = ret;
    }
}
  _$jscoverage['router/index.js'][80]++;
  if ("function" != typeof fn) {
    _$jscoverage['router/index.js'][81]++;
    throw new Error("invalid param() call for " + name + ", got " + fn);
  }
  _$jscoverage['router/index.js'][84]++;
  (this.params[name] = this.params[name] || []).push(fn);
  _$jscoverage['router/index.js'][85]++;
  return this;
});
_$jscoverage['router/index.js'][95]++;
Router.prototype.all = (function () {
  _$jscoverage['router/index.js'][96]++;
  return this.find((function () {
  _$jscoverage['router/index.js'][97]++;
  return true;
}));
});
_$jscoverage['router/index.js'][111]++;
Router.prototype.remove = (function (route) {
  _$jscoverage['router/index.js'][112]++;
  var routes = this.map[route.method], len = routes.length;
  _$jscoverage['router/index.js'][116]++;
  var i = this.routes.indexOf(route);
  _$jscoverage['router/index.js'][117]++;
  this.routes.splice(i, 1);
  _$jscoverage['router/index.js'][120]++;
  for (var i = 0; i < len; ++i) {
    _$jscoverage['router/index.js'][121]++;
    if (route == routes[i]) {
      _$jscoverage['router/index.js'][122]++;
      routes.splice(i, 1);
      _$jscoverage['router/index.js'][123]++;
      return true;
    }
}
});
_$jscoverage['router/index.js'][137]++;
Router.prototype.lookup = (function (method, path) {
  _$jscoverage['router/index.js'][138]++;
  return this.find((function (route) {
  _$jscoverage['router/index.js'][139]++;
  return path == route.path && (route.method == method || method == "all");
}));
});
_$jscoverage['router/index.js'][171]++;
Router.prototype.find = (function (fn) {
  _$jscoverage['router/index.js'][172]++;
  var len = methods.length, ret = new Collection(this), method, routes, route;
  _$jscoverage['router/index.js'][178]++;
  for (var i = 0; i < len; ++i) {
    _$jscoverage['router/index.js'][179]++;
    method = methods[i];
    _$jscoverage['router/index.js'][180]++;
    routes = this.map[method];
    _$jscoverage['router/index.js'][181]++;
    if (! routes) {
      _$jscoverage['router/index.js'][181]++;
      continue;
    }
    _$jscoverage['router/index.js'][182]++;
    for (var j = 0, jlen = routes.length; j < jlen; ++j) {
      _$jscoverage['router/index.js'][183]++;
      route = routes[j];
      _$jscoverage['router/index.js'][184]++;
      if (fn(route)) {
        _$jscoverage['router/index.js'][184]++;
        ret.push(route);
      }
}
}
  _$jscoverage['router/index.js'][188]++;
  return ret;
});
_$jscoverage['router/index.js'][200]++;
Router.prototype._dispatch = (function (req, res, next) {
  _$jscoverage['router/index.js'][201]++;
  var params = this.params, self = this;
  _$jscoverage['router/index.js'][204]++;
  debug("dispatching %s %s", req.method, req.url);
  _$jscoverage['router/index.js'][207]++;
  (function pass(i, err) {
  _$jscoverage['router/index.js'][208]++;
  var paramCallbacks, paramIndex = 0, paramVal, route, keys, key, ret;
  _$jscoverage['router/index.js'][217]++;
  function nextRoute(err) {
    _$jscoverage['router/index.js'][218]++;
    pass(req._route_index + 1, err);
}
  _$jscoverage['router/index.js'][222]++;
  req.route = route = self.match(req, i);
  _$jscoverage['router/index.js'][225]++;
  if (! route && "OPTIONS" == req.method) {
    _$jscoverage['router/index.js'][225]++;
    return self._options(req, res);
  }
  _$jscoverage['router/index.js'][228]++;
  if (! route) {
    _$jscoverage['router/index.js'][228]++;
    return next(err);
  }
  _$jscoverage['router/index.js'][229]++;
  debug("matched %s %s", route.method, route.path);
  _$jscoverage['router/index.js'][233]++;
  req.params = route.params;
  _$jscoverage['router/index.js'][234]++;
  keys = route.keys;
  _$jscoverage['router/index.js'][235]++;
  i = 0;
  _$jscoverage['router/index.js'][238]++;
  function param(err) {
    _$jscoverage['router/index.js'][239]++;
    paramIndex = 0;
    _$jscoverage['router/index.js'][240]++;
    key = keys[i++];
    _$jscoverage['router/index.js'][241]++;
    paramVal = key && req.params[key.name];
    _$jscoverage['router/index.js'][242]++;
    paramCallbacks = key && params[key.name];
    _$jscoverage['router/index.js'][244]++;
    try {
      _$jscoverage['router/index.js'][245]++;
      if ("route" == err) {
        _$jscoverage['router/index.js'][246]++;
        nextRoute();
      }
      else {
        _$jscoverage['router/index.js'][247]++;
        if (err) {
          _$jscoverage['router/index.js'][248]++;
          i = 0;
          _$jscoverage['router/index.js'][249]++;
          callbacks(err);
        }
        else {
          _$jscoverage['router/index.js'][250]++;
          if (paramCallbacks && undefined !== paramVal) {
            _$jscoverage['router/index.js'][251]++;
            paramCallback();
          }
          else {
            _$jscoverage['router/index.js'][252]++;
            if (key) {
              _$jscoverage['router/index.js'][253]++;
              param();
            }
            else {
              _$jscoverage['router/index.js'][255]++;
              i = 0;
              _$jscoverage['router/index.js'][256]++;
              callbacks();
            }
          }
        }
      }
    }
    catch (err) {
      _$jscoverage['router/index.js'][259]++;
      param(err);
    }
}
  _$jscoverage['router/index.js'][261]++;
  ;
  _$jscoverage['router/index.js'][263]++;
  param(err);
  _$jscoverage['router/index.js'][266]++;
  function paramCallback(err) {
    _$jscoverage['router/index.js'][267]++;
    var fn = paramCallbacks[paramIndex++];
    _$jscoverage['router/index.js'][268]++;
    if (err || ! fn) {
      _$jscoverage['router/index.js'][268]++;
      return param(err);
    }
    _$jscoverage['router/index.js'][269]++;
    fn(req, res, paramCallback, paramVal, key.name);
}
  _$jscoverage['router/index.js'][273]++;
  function callbacks(err) {
    _$jscoverage['router/index.js'][274]++;
    var fn = route.callbacks[i++];
    _$jscoverage['router/index.js'][275]++;
    try {
      _$jscoverage['router/index.js'][276]++;
      if ("route" == err) {
        _$jscoverage['router/index.js'][277]++;
        nextRoute();
      }
      else {
        _$jscoverage['router/index.js'][278]++;
        if (err && fn) {
          _$jscoverage['router/index.js'][279]++;
          if (fn.length < 4) {
            _$jscoverage['router/index.js'][279]++;
            return callbacks(err);
          }
          _$jscoverage['router/index.js'][280]++;
          fn(err, req, res, callbacks);
        }
        else {
          _$jscoverage['router/index.js'][281]++;
          if (fn) {
            _$jscoverage['router/index.js'][282]++;
            fn(req, res, callbacks);
          }
          else {
            _$jscoverage['router/index.js'][284]++;
            nextRoute(err);
          }
        }
      }
    }
    catch (err) {
      _$jscoverage['router/index.js'][287]++;
      callbacks(err);
    }
}
})(0);
});
_$jscoverage['router/index.js'][301]++;
Router.prototype._options = (function (req, res) {
  _$jscoverage['router/index.js'][302]++;
  var path = parse(req.url).pathname, body = this._optionsFor(path).join(",");
  _$jscoverage['router/index.js'][304]++;
  res.set("Allow", body).send(body);
});
_$jscoverage['router/index.js'][315]++;
Router.prototype._optionsFor = (function (path) {
  _$jscoverage['router/index.js'][316]++;
  var self = this;
  _$jscoverage['router/index.js'][317]++;
  return methods.filter((function (method) {
  _$jscoverage['router/index.js'][318]++;
  var routes = self.map[method];
  _$jscoverage['router/index.js'][319]++;
  if (! routes || "options" == method) {
    _$jscoverage['router/index.js'][319]++;
    return;
  }
  _$jscoverage['router/index.js'][320]++;
  for (var i = 0, len = routes.length; i < len; ++i) {
    _$jscoverage['router/index.js'][321]++;
    if (routes[i].match(path)) {
      _$jscoverage['router/index.js'][321]++;
      return true;
    }
}
})).map((function (method) {
  _$jscoverage['router/index.js'][324]++;
  return method.toUpperCase();
}));
});
_$jscoverage['router/index.js'][339]++;
Router.prototype.match = (function (req, i, head) {
  _$jscoverage['router/index.js'][340]++;
  var method = req.method.toLowerCase(), url = parse(req.url), path = url.pathname, routes = this.map, i = i || 0, captures, route, keys;
  _$jscoverage['router/index.js'][351]++;
  if (! head && "head" == method) {
    _$jscoverage['router/index.js'][353]++;
    route = this.match(req, i, true);
    _$jscoverage['router/index.js'][354]++;
    if (route) {
      _$jscoverage['router/index.js'][354]++;
      return route;
    }
    _$jscoverage['router/index.js'][358]++;
    method = "get";
  }
  _$jscoverage['router/index.js'][362]++;
  if (routes = routes[method]) {
    _$jscoverage['router/index.js'][365]++;
    for (var len = routes.length; i < len; ++i) {
      _$jscoverage['router/index.js'][366]++;
      route = routes[i];
      _$jscoverage['router/index.js'][367]++;
      if (captures = route.match(path)) {
        _$jscoverage['router/index.js'][368]++;
        keys = route.keys;
        _$jscoverage['router/index.js'][369]++;
        route.params = [];
        _$jscoverage['router/index.js'][372]++;
        for (var j = 1, jlen = captures.length; j < jlen; ++j) {
          _$jscoverage['router/index.js'][373]++;
          var key = keys[j - 1], val = "string" == typeof captures[j]? decodeURIComponent(captures[j]): captures[j];
          _$jscoverage['router/index.js'][377]++;
          if (key) {
            _$jscoverage['router/index.js'][378]++;
            route.params[key.name] = val;
          }
          else {
            _$jscoverage['router/index.js'][380]++;
            route.params.push(val);
          }
}
        _$jscoverage['router/index.js'][385]++;
        req._route_index = i;
        _$jscoverage['router/index.js'][386]++;
        return route;
      }
}
  }
});
_$jscoverage['router/index.js'][402]++;
Router.prototype.route = (function (method, path, callbacks) {
  _$jscoverage['router/index.js'][403]++;
  var app = this.app, method = method.toLowerCase(), callbacks = utils.flatten([].slice.call(arguments, 2));
  _$jscoverage['router/index.js'][408]++;
  if (! path) {
    _$jscoverage['router/index.js'][408]++;
    throw new Error("Router#" + method + "() requires a path");
  }
  _$jscoverage['router/index.js'][411]++;
  debug("defined %s %s", method, path);
  _$jscoverage['router/index.js'][412]++;
  var route = new Route(method, path, callbacks, {sensitive: this.caseSensitive, strict: this.strict});
  _$jscoverage['router/index.js'][418]++;
  (this.map[method] = this.map[method] || []).push(route);
  _$jscoverage['router/index.js'][419]++;
  this.routes.push(route);
  _$jscoverage['router/index.js'][420]++;
  return this;
});
_$jscoverage['router/index.js'].source = ["/*!"," * Express - Router"," * Copyright(c) 2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;"," * MIT Licensed"," */","","/**"," * Module dependencies."," */","","var Route = require('./route')","  , Collection = require('./collection')","  , utils = require('../utils')","  , debug = require('debug')('express:router')","  , parse = require('url').parse;","","/**"," * Expose `Router` constructor."," */","","exports = module.exports = Router;","","/**"," * Expose HTTP methods."," */","","var methods = exports.methods = require('./methods');","","/**"," * Initialize a new `Router` with the given `options`."," * "," * @param {Object} options"," * @api private"," */","","function Router(options) {","  options = options || {};","  var self = this;","  this.routes = new Collection;","  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 &lt; 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;","};","","/**"," * Return a `Collection` of all routes defined."," *"," * @return {Collection}"," * @api public"," */","","Router.prototype.all = function(){","  return this.find(function(){","    return true;","  });","};","","/**"," * Remove the given `route`, returns"," * a bool indicating if the route was present"," * or not."," *"," * @param {Route} route"," * @return {Boolean}"," * @api public"," */","","Router.prototype.remove = function(route){","  var routes = this.map[route.method]","    , len = routes.length;","","  // remove from array","  var i = this.routes.indexOf(route);","  this.routes.splice(i, 1);","","  // remove from map","  for (var i = 0; i &lt; len; ++i) {","    if (route == routes[i]) {","      routes.splice(i, 1);","      return true;","    }","  }","};","","/**"," * Return routes with route paths matching `path`."," *"," * @param {String} method"," * @param {String} path"," * @return {Collection}"," * @api public"," */","","Router.prototype.lookup = function(method, path){","  return this.find(function(route){","    return path == route.path","      &amp;&amp; (route.method == method","      || method == 'all');","  });","};","","// /**","//  * Return routes with regexps that match the given `url`.","//  *","//  * @param {String} method","//  * @param {String} url","//  * @return {Collection}","//  * @api public","//  */","// ","// Router.prototype.match = function(method, url){","//   return this.find(function(route){","//     return route.match(url)","//       &amp;&amp; (route.method == method","//       || method == 'all');","//   });","// };","","/**"," * Find routes based on the return value of `fn`"," * which is invoked once per route."," *"," * @param {Function} fn"," * @return {Collection}"," * @api public"," */","","Router.prototype.find = function(fn){","  var len = methods.length","    , ret = new Collection(this)","    , method","    , routes","    , route;","","  for (var i = 0; i &lt; len; ++i) {","    method = methods[i];","    routes = this.map[method];","    if (!routes) continue;","    for (var j = 0, jlen = routes.length; j &lt; jlen; ++j) {","      route = routes[j];","      if (fn(route)) ret.push(route);","    }","  }","","  return ret;","};","","/**"," * 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', req.method, req.url);","","  // route dispatch","  (function pass(i, err){","    var paramCallbacks","      , paramIndex = 0","      , paramVal","      , route","      , keys","      , key","      , ret;","","    // match next route","    function nextRoute(err) {","      pass(req._route_index + 1, err);","    }","","    // match route","    req.route = route = self.match(req, i);","","    // implied OPTIONS","    if (!route &amp;&amp; 'OPTIONS' == req.method) return self._options(req, res);","","    // 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 &amp;&amp; req.params[key.name];","      paramCallbacks = key &amp;&amp; params[key.name];","","      try {","        if ('route' == err) {","          nextRoute();","        } else if (err) {","          i = 0;","          callbacks(err);","        } else if (paramCallbacks &amp;&amp; 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 &amp;&amp; fn) {","          if (fn.length &lt; 4) return callbacks(err);","          fn(err, req, res, callbacks);","        } else if (fn) {","          fn(req, res, callbacks);","        } else {","          nextRoute(err);","        }","      } catch (err) {","        callbacks(err);","      }","    }","  })(0);","};","","/**"," * Respond to __OPTIONS__ method."," *"," * @param {IncomingMessage} req"," * @param {ServerResponse} res"," * @api private"," */","","Router.prototype._options = function(req, res){","  var path = parse(req.url).pathname","    , body = this._optionsFor(path).join(',');","  res.set('Allow', body).send(body);","};","","/**"," * Return an array of HTTP verbs or \"options\" for `path`."," *"," * @param {String} path"," * @return {Array}"," * @api private"," */","","Router.prototype._optionsFor = function(path){","  var self = this;","  return methods.filter(function(method){","    var routes = self.map[method];","    if (!routes || 'options' == method) return;","    for (var i = 0, len = routes.length; i &lt; len; ++i) {","      if (routes[i].match(path)) return true;","    }","  }).map(function(method){","    return method.toUpperCase();","  });","};","","/**"," * 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.match = function(req, i, head){","  var method = req.method.toLowerCase()","    , url = parse(req.url)","    , path = url.pathname","    , routes = this.map","    , i = i || 0","    , captures","    , route","    , keys;","","  // HEAD support","  // TODO: clean this up","  if (!head &amp;&amp; 'head' == method) {","    // attempt lookup","    route = this.match(req, i, true);","    if (route) return route;","","    // default to GET as res.render() / res.send()","    // etc support HEAD","     method = 'get';","  }","","  // routes for this method","  if (routes = routes[method]) {","","    // matching routes","    for (var len = routes.length; i &lt; len; ++i) {","      route = routes[i];","      if (captures = route.match(path)) {","        keys = route.keys;","        route.params = [];","","        // params from capture groups","        for (var j = 1, jlen = captures.length; j &lt; jlen; ++j) {","          var key = keys[j-1]","            , val = 'string' == typeof captures[j]","              ? decodeURIComponent(captures[j])","              : captures[j];","          if (key) {","            route.params[key.name] = val;","          } else {","            route.params.push(val);","          }","        }","","        // all done","        req._route_index = i;","        return route;","      }","    }","  }","};","","/**"," * 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 app = this.app","    , method = method.toLowerCase()","    , callbacks = utils.flatten([].slice.call(arguments, 2));","","  // ensure path was given","  if (!path) throw new Error('Router#' + method + '() requires a path');","","  // 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);","  this.routes.push(route);","  return this;","};"];
