express之layer.js

lib/router/layer.js

module.exports = Layer;
//Layer构造函数,一个Layer可以属于router,也可以属于Route
//当调用router的route方法时,Layer作为Route对象的中间层,它的path与创建的Route的path一样,它的handle为Route的dispatch方法
//当调用router的use方法时,Layer的handle为use添加的中间件方法,可能是一个router对象、也可能是一个标准的中间件方法
//当属于Route时,代表一个使用all、get、post方法添加的路由处理方法,此时Layer是有method的,但是其path为/,可以做方法匹配,但是不做路径匹配
function Layer(path, options, fn) {
  //确保作为构造函数调用
  if (!(this instanceof Layer)) {
    return new Layer(path, options, fn);
  }
  debug('new %o', path)
  var opts = options || {};
  //设置处理函数,可能为中间件,此时可能为普通中间件函数、Router对象、express实例的包装函数
  //可能为指定http方法的处理函数、Route的dispatch方法
  //一个handle只可能处理请求或者err,必须是标准的请求处理函数req、res、next或者标准的错误处理函数err、req、res、next
  this.handle = fn;
  //函数名或者匿名函数,因为Router本身就是匿名函数
  this.name = fn.name || '<anonymous>';
  this.params = undefined;
  //路径,属于Router时,代表挂载的中间件路径
  //属于Route时,为/
  this.path = undefined;
  //正则
  this.regexp = pathRegexp(path, this.keys = [], opts);
  // 快速匹配
  //路径是否为*,代表匹配所有路径
  this.regexp.fast_star = path === '*'
  //path为/,代表匹配根路径
  this.regexp.fast_slash = path === '/' && opts.end === false
}

//错误处理函数
Layer.prototype.handle_error = function handle_error(error, req, res, next) {
  //内部处理函数还是handle
  var fn = this.handle;
  //函数的参数不是四个,err、req、res、next,即不是标准的express错误处理函数,继续向下传递
  if (fn.length !== 4) {
    return next(error);
  }
  try {
    fn(error, req, res, next);
  } catch (err) {
    next(err);
  }
};

//请求处理函数
Layer.prototype.handle_request = function handle(req, res, next) {
  var fn = this.handle;
  //如果参数多于三个,说明不是标准的请求处理函数
  if (fn.length > 3) {
    return next();
  }
  try {
    fn(req, res, next);
  } catch (err) {
    next(err);
  }
};

//Layer是否匹配指定路径
Layer.prototype.match = function match(path) {
  var match
  if (path != null) {
    //当Layer属于一个Route时,path为/, /肯定匹配所有路径开始的/,因为每个路径开始都是/
    if (this.regexp.fast_slash) {
      //此时路径参数为空,因为Layer匹配部分只有一个/其他部分另外处理
      this.params = {}
      //path为空
      this.path = ''
      return true
    }
    //当Layer路径为*代表匹配所有路由,此时匹配部分为参数path的全部
    if (this.regexp.fast_star) {
      //路径参数
      this.params = {'0': decode_param(path)}
      //路径
      this.path = path
      return true
    }
    //其他普通情况,执行正则匹配
    match = this.regexp.exec(path)
  }
  //没有匹配项
  if (!match) {
    //路径与路径参数都为空
    this.params = undefined;
    this.path = undefined;
    return false;
  }
  //路径为第一个匹配项
  this.params = {};
  this.path = match[0]
  //路径参数
  var keys = this.keys;
  var params = this.params;
  //遍历匹配结果数组,从下标1开始,因为0已经给了path
  for (var i = 1; i < match.length; i++) {
    var key = keys[i - 1];
    //获取路径参数名
    var prop = key.name;
    //解码匹配项为路径参数值
    var val = decode_param(match[i])
    if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
      //将路径参数赋值给params属性
      params[prop] = val;
    }
  }
  return true;
};

//解码路径参数值
function decode_param(val) {
  //不是字符串或者长度为0,直接返回
  if (typeof val !== 'string' || val.length === 0) {
    return val;
  }
  try {
    //url组件解码
    return decodeURIComponent(val);
  } catch (err) {
    if (err instanceof URIError) {
      err.message = 'Failed to decode param \'' + val + '\'';
      err.status = err.statusCode = 400;
    }
    throw err;
  }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值