Вход Регистрация
Файл: error-kitty/node_modules/express/lib/router/index.js
Строк: 472
<?php
/**
 * Module dependencies.
 */

var Route = require('./route');
var 
Layer = require('./layer');
var 
methods = require('methods');
var 
mixin = require('utils-merge');
var 
debug = require('debug')('express:router');
var 
parseUrl = require('parseurl');
var 
utils = require('../utils');

/**
 * Module variables.
 */

var objectRegExp = /^[object (S+)]$/;
var 
slice = Array.prototype.slice;
var 
toString Object.prototype.toString;

/**
 * Initialize a new `Router` with the given `options`.
 *
 * @param {Object} options
 * @return {Router} which is an callable function
 * @api public
 */

var proto module.exports = function(options) {
  
options options || {};

  function 
router(reqresnext) {
    
router.handle(reqresnext);
  }

  
// mixin Router class functions
  
router.__proto__ proto;

  
router.params = {};
  
router._params = [];
  
router.caseSensitive options.caseSensitive;
  
router.mergeParams options.mergeParams;
  
router.strict options.strict;
  
router.stack = [];

  return 
router;
};

/**
 * Map the given param placeholder `name`(s) to the given callback.
 *
 * Parameter mapping is used to provide pre-conditions to routes
 * which use normalized placeholders. For example a _:user_id_ parameter
 * could automatically load a user's information from the database without
 * any additional code,
 *
 * The callback uses the same signature as middleware, the only difference
 * being that the value of the placeholder is passed, in this case the _id_
 * of the user. Once the `next()` function is invoked, just like middleware
 * it will continue on to execute the route, or subsequent parameter functions.
 *
 * Just like in middleware, you must either respond to the request or call next
 * to avoid stalling the request.
 *
 *  app.param('user_id', function(req, res, next, id){
 *    User.find(id, function(err, user){
 *      if (err) {
 *        return next(err);
 *      } else if (!user) {
 *        return next(new Error('failed to load user'));
 *      }
 *      req.user = user;
 *      next();
 *    });
 *  });
 *
 * @param {String} name
 * @param {Function} fn
 * @return {app} for chaining
 * @api public
 */

proto.param = function(namefn){
  
// param logic
  
if ('function' == typeof name) {
    
this._params.push(name);
    return;
  }

  
// apply param functions
  
var params this._params;
  var 
len params.length;
  var 
ret;

  if (
name[0] === ':') {
    
name name.substr(1);
  }

  for (var 
0len; ++i) {
    if (
ret params[i](namefn)) {
      
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;
};

/**
 * Dispatch a req, res into the router.
 *
 * @api private
 */

proto.handle = function(reqresdone) {
  var 
self this;

  
debug('dispatching %s %s'req.methodreq.url);

  var 
search req.url.indexOf('?');
  var 
pathlength search search req.url.length;
  var 
fqdn req.url.substr(0pathlength).indexOf('://');
  var 
protohost fqdn req.url.substr(0req.url.indexOf('/'fqdn)) : '';
  var 
idx 0;
  var 
removed '';
  var 
slashAdded false;
  var 
paramcalled = {};

  
// store options for OPTIONS request
  // only used if OPTIONS request
  
var options = [];

  
// middleware and routes
  
var stack self.stack;

  
// manage inter-router variables
  
var parentParams req.params;
  var 
parentUrl req.baseUrl || '';
  
done restore(donereq'baseUrl''next''params');

  
// setup next layer
  
req.next next;

  
// for options requests, respond with a default if nothing else responds
  
if (req.method === 'OPTIONS') {
    
done wrap(done, function(olderr) {
      if (
err || options.length === 0) return old(err);

      var 
body options.join(',');
      return 
res.set('Allow'body).send(body);
    });
  }

  
// setup basic req values
  
req.baseUrl parentUrl;
  
req.originalUrl req.originalUrl || req.url;

  
next();

  function 
next(err) {
    var 
layerError err === 'route'
      
null
      
err;

    var 
layer stack[idx++];

    if (
slashAdded) {
      
req.url req.url.substr(1);
      
slashAdded false;
    }

    if (
removed.length !== 0) {
      
req.baseUrl parentUrl;
      
req.url protohost removed req.url.substr(protohost.length);
      
removed '';
    }

    if (!
layer) {
      return 
done(layerError);
    }

    
self.match_layer(layerreqres, function (errpath) {
      if (
err || path === undefined) {
        return 
next(layerError || err);
      }

      
// route object and not middleware
      
var route layer.route;

      
// if final route, then we support options
      
if (route) {
        
// we don't run any routes with error first
        
if (layerError) {
          return 
next(layerError);
        }

        var 
method req.method;
        var 
has_method route._handles_method(method);

        
// build up automatic options response
        
if (!has_method && method === 'OPTIONS') {
          
options.push.apply(optionsroute._options());
        }

        
// don't even bother
        
if (!has_method && method !== 'HEAD') {
          return 
next();
        }

        
// we can now dispatch to the route
        
req.route route;
      }

      
// Capture one-time layer values
      
req.params self.mergeParams
        
mergeParams(layer.paramsparentParams)
        : 
layer.params;
      var 
layerPath layer.path;

      
// this should be done for the layer
      
self.process_params(layerparamcalledreqres, function (err) {
        if (
err) {
          return 
next(layerError || err);
        }

        if (
route) {
          return 
layer.handle_request(reqresnext);
        }

        
trim_prefix(layerlayerErrorlayerPathpath);
      });
    });
  }

  function 
trim_prefix(layerlayerErrorlayerPathpath) {
    var 
path[layerPath.length];
    if (
&& '/' !== && '.' !== c) return next(layerError);

     
// Trim off the part of the url that matches the route
     // middleware (.use stuff) needs to have the path stripped
    
if (layerPath.length !== 0) {
      
debug('trim prefix (%s) from url %s'layerPathreq.url);
      
removed layerPath;
      
req.url protohost req.url.substr(protohost.length removed.length);

      
// Ensure leading slash
      
if (!fqdn && req.url[0] !== '/') {
        
req.url '/' req.url;
        
slashAdded true;
      }

      
// Setup base URL (no trailing slash)
      
req.baseUrl parentUrl + (removed[removed.length 1] === '/'
        
removed.substring(0removed.length 1)
        : 
removed);
    }

    
debug('%s %s : %s'layer.namelayerPathreq.originalUrl);

    if (
layerError) {
      
layer.handle_error(layerErrorreqresnext);
    } else {
      
layer.handle_request(reqresnext);
    }
  }
};

/**
 * Match request to a layer.
 *
 * @api private
 */

proto.match_layer = function match_layer(layerreqresdone) {
  var 
error null;
  var 
path;

  try {
    
path parseUrl(req).pathname;

    if (!
layer.match(path)) {
      
path undefined;
    }
  } catch (
err) {
    
error err;
  }

  
done(errorpath);
};

/**
 * Process any parameters for the layer.
 *
 * @api private
 */

proto.process_params = function(layercalledreqresdone) {
  var 
params this.params;

  
// captured parameters from the layer, keys and values
  
var keys layer.keys;

  
// fast track
  
if (!keys || keys.length === 0) {
    return 
done();
  }

  var 
0;
  var 
name;
  var 
paramIndex 0;
  var 
key;
  var 
paramVal;
  var 
paramCallbacks;
  var 
paramCalled;

  
// process params in order
  // param callbacks can be async
  
function param(err) {
    if (
err) {
      return 
done(err);
    }

    if (
>= keys.length ) {
      return 
done();
    }

    
paramIndex 0;
    
key keys[i++];

    if (!
key) {
      return 
done();
    }

    
name key.name;
    
paramVal req.params[name];
    
paramCallbacks params[name];
    
paramCalled called[name];

    if (
paramVal === undefined || !paramCallbacks) {
      return 
param();
    }

    
// param previously called with same value or error occurred
    
if (paramCalled && (paramCalled.error || paramCalled.match === paramVal)) {
      
// restore value
      
req.params[name] = paramCalled.value;

      
// next param
      
return param(paramCalled.error);
    }

    
called[name] = paramCalled = {
      
errornull,
      
matchparamVal,
      
valueparamVal
    
};

    
paramCallback();
  }

  
// single param callbacks
  
function paramCallback(err) {
    var 
fn paramCallbacks[paramIndex++];

    
// store updated value
    
paramCalled.value req.params[key.name];

    if (
err) {
      
// store error
      
paramCalled.error err;
      
param(err);
      return;
    }

    if (!
fn) return param();

    try {
      
fn(reqresparamCallbackparamValkey.name);
    } catch (
e) {
      
paramCallback(e);
    }
  }

  
param();
};

/**
 * Use the given middleware function, with optional path, defaulting to "/".
 *
 * Use (like `.all`) will run for any http METHOD, but it will not add
 * handlers for those methods so OPTIONS requests will not consider `.use`
 * functions even if they could respond.
 *
 * The other difference is that _route_ path is stripped and not visible
 * to the handler function. The main effect of this feature is that mounted
 * handlers can operate without any code changes regardless of the "prefix"
 * pathname.
 *
 * @api public
 */

proto.use = function use(fn) {
  var 
offset 0;
  var 
path '/';
  var 
self this;

  
// default path to '/'
  // disambiguate router.use([fn])
  
if (typeof fn !== 'function') {
    var 
arg fn;

    while (Array.
isArray(arg) && arg.length !== 0) {
      
arg arg[0];
    }

    
// first arg is the path
    
if (typeof arg !== 'function') {
      
offset 1;
      
path fn;
    }
  }

  var 
callbacks utils.flatten(slice.call(argumentsoffset));

  if (
callbacks.length === 0) {
    throw new 
TypeError('Router.use() requires middleware functions');
  }

  
callbacks.forEach(function (fn) {
    if (
typeof fn !== 'function') {
      throw new 
TypeError('Router.use() requires middleware function but got a ' gettype(fn));
    }

    
// add the middleware
    
debug('use %s %s'pathfn.name || '<anonymous>');

    var 
layer = new Layer(path, {
      
sensitiveself.caseSensitive,
      
strictfalse,
      
endfalse
    
}, fn);

    
layer.route undefined;

    
self.stack.push(layer);
  });

  return 
this;
};

/**
 * Create a new Route for the given path.
 *
 * Each route contains a separate middleware stack and VERB handlers.
 *
 * See the Route api documentation for details on adding handlers
 * and middleware to routes.
 *
 * @param {String} path
 * @return {Route}
 * @api public
 */

proto.route = function(path){
  var 
route = new Route(path);

  var 
layer = new Layer(path, {
    
sensitivethis.caseSensitive,
    
strictthis.strict,
    
endtrue
  
}, route.dispatch.bind(route));

  
layer.route route;

  
this.stack.push(layer);
  return 
route;
};

// create Router#VERB functions
methods.concat('all').forEach(function(method){
  
proto[method] = function(path){
    var 
route this.route(path)
    
route[method].apply(routeslice.call(arguments1));
    return 
this;
  };
});

// get type for error message
function gettype(obj) {
  var 
type typeof obj;

  if (
type !== 'object') {
    return 
type;
  }

  
// inspect [[Class]] for objects
  
return toString.call(obj)
    .
replace(objectRegExp'$1');
}

// merge params with parent params
function mergeParams(paramsparent) {
  if (
typeof parent !== 'object' || !parent) {
    return 
params;
  }

  
// make copy of parent for base
  
var obj mixin({}, parent);

  
// simple non-numeric merging
  
if (!(0 in params) || !(0 in parent)) {
    return 
mixin(objparams);
  }

  var 
0;
  var 
0;

  
// determine numeric gaps
  
while (=== || o in parent) {
    if (
i in paramsi++;
    if (
o in parento++;
  }

  
// offset numeric indices in params before merge
  
for (i--; >= 0i--) {
    
params[o] = params[i];

    
// create holes for the merge when necessary
    
if (o) {
      
delete params[i];
    }
  }

  return 
mixin(parentparams);
}

// restore obj props after function
function restore(fnobj) {
  var 
props = new Array(arguments.length 2);
  var 
vals = new Array(arguments.length 2);

  for (var 
0props.lengthi++) {
    
props[i] = arguments[2];
    
vals[i] = obj[props[i]];
  }

  return function(
err){
    
// restore vals
    
for (var 0props.lengthi++) {
      
obj[props[i]] = vals[i];
    }

    return 
fn.apply(thisarguments);
  };
}

// wrap a function
function wrap(oldfn) {
  return function 
proxy() {
    var 
args = new Array(arguments.length 1);

    
args[0] = old;
    for (var 
0len arguments.lengthleni++) {
      
args[1] = arguments[i];
    }

    
fn.apply(thisargs);
  };
}
?>
Онлайн: 4
Реклама