express之request.js
发布日期:2021-05-28 16:23:58 浏览次数:30 分类:技术文章

本文共 6160 字,大约阅读时间需要 20 分钟。

lib/request.js//请求原型对象继承了http原生的请求原型var req = Object.create(http.IncomingMessage.prototype)module.exports = req//get、header方法都是获取指定名称请求头req.get =req.header = function header(name) {  //名称不存在,抛出错误  if (!name) {    throw new TypeError('name argument is required to req.get');  }  //名称不是字符串,抛出错误  if (typeof name !== 'string') {    throw new TypeError('name must be a string to req.get');  }  //名称转化为小写,内部都是以小写来存储的  var lc = name.toLowerCase();  //特殊处理referer、referrer  switch (lc) {    case 'referer':    case 'referrer':      return this.headers.referrer        || this.headers.referer;    default:    //默认返回headers中属性值,这个headers是IncomingMessage上的属性      return this.headers[lc];  }};//检查指定MIME类型是否可以接受//参数可以为application/json等标准MIME类型,也可以是json、html等扩展名//如果指定类型可以接收,返回它,如果不可接受,返回undefined//如果为类型数组,返回最佳匹配//但是在哪设置可以接受的MIME类型?req的属性上吗req.accepts = function(){  var accept = accepts(this);  return accept.types.apply(accept, arguments);};//给定请求编码是否可接受req.acceptsEncodings = function(){  var accept = accepts(this);  return accept.encodings.apply(accept, arguments);};//不带s的函数已经废弃req.acceptsEncoding = deprecate.function(req.acceptsEncodings,  'req.acceptsEncoding: Use acceptsEncodings instead');//指定字符集是否可接受req.acceptsCharsets = function(){  var accept = accepts(this);  return accept.charsets.apply(accept, arguments);};req.acceptsCharset = deprecate.function(req.acceptsCharsets,  'req.acceptsCharset: Use acceptsCharsets instead');//指定语言是否可接受req.acceptsLanguages = function(){  var accept = accepts(this);  return accept.languages.apply(accept, arguments);};req.acceptsLanguage = deprecate.function(req.acceptsLanguages,  'req.acceptsLanguage: Use acceptsLanguages instead');//获取请求头中Range字段,解析后返回//Range字段用来设置要下载资源的字节返范围req.range = function range(size, options) {  //获取Range请求头  var range = this.get('Range');  //不存在返回undefined  if (!range) return;  //解析字段,返回一个对象数组,对象有start、end属性指明要下载的字节位置  return parseRange(size, range, options);};/** * Return the value of param `name` when present or `defaultValue`. * *  - Checks route placeholders, ex: _/user/:id_ *  - Checks body params, ex: id=12, {"id":12} *  - Checks query string params, ex: ?id=12 * * To utilize request bodies, `req.body` * should be an object. This can be done by using * the `bodyParser()` middleware. * * @param {String} name * @param {Mixed} [defaultValue] * @return {String} * @public *///获取指定名称参数,没有返回默认值//获取参数顺序为:路由占位符如:id形式、请求体参数、查询字符串参数req.param = function param(name, defaultValue) {  //分别获取路由占位符参数对象、请求体参数对象、查询字符串参数对象  var params = this.params || {};  var body = this.body || {};  var query = this.query || {};  //已废弃  var args = arguments.length === 1    ? 'name'    : 'name, default';  deprecate('req.param(' + args + '): Use req.params, req.body, or req.query instead');  //依次查找返回  if (null != params[name] && params.hasOwnProperty(name)) return params[name];  if (null != body[name]) return body[name];  if (null != query[name]) return query[name];  return defaultValue;};//根据content-type请求头检查请求是否是指定MIME类型req.is = function is(types) {  var arr = types;  //转化为参数数组  if (!Array.isArray(types)) {    arr = new Array(arguments.length);    for (var i = 0; i < arr.length; i++) {      arr[i] = arguments[i];    }  }  //使用库来检查  return typeis(this, arr);};//protocol的getter函数defineGetter(req, 'protocol', function protocol(){  //socket连接如果是加密的为https,否则为http  var proto = this.connection.encrypted    ? 'https'    : 'http';  var trust = this.app.get('trust proxy fn');  //信任代理函数  if (!trust(this.connection.remoteAddress, 0)) {    return proto;  }  //从x-forwarded-proto请求头获取协议,当一个请求最初发出时的协议,由反向代理设置  var header = this.get('X-Forwarded-Proto') || proto  var index = header.indexOf(',')  return index !== -1    ? header.substring(0, index).trim()    : header.trim()});//如果是https协议,返回truedefineGetter(req, 'secure', function secure(){  return this.protocol === 'https';});//远程ipdefineGetter(req, 'ip', function ip(){  var trust = this.app.get('trust proxy fn');  return proxyaddr(this, trust);});//所有ip,包含了代理服务器ipdefineGetter(req, 'ips', function ips() {  var trust = this.app.get('trust proxy fn');  var addrs = proxyaddr.all(this, trust);  addrs.reverse().pop()  return addrs});//子域名数组defineGetter(req, 'subdomains', function subdomains() {  //域名  var hostname = this.hostname;  if (!hostname) return [];  //子域名偏移  var offset = this.app.get('subdomain offset');  var subdomains = !isIP(hostname)    ? hostname.split('.').reverse()    : [hostname];  return subdomains.slice(offset);});//url解析后的pathname,代表了端口号后面查询?前面的部分defineGetter(req, 'path', function path() {  return parse(this).pathname;});//域名defineGetter(req, 'hostname', function hostname(){  //信任代理函数  var trust = this.app.get('trust proxy fn');  //代理域名  var host = this.get('X-Forwarded-Host');  //域名不存在  if (!host || !trust(this.connection.remoteAddress, 0)) {    //返回请求头中域名    host = this.get('Host');  }  if (!host) return;  // IPv6 literal support  var offset = host[0] === '['    ? host.indexOf(']') + 1    : 0;  var index = host.indexOf(':', offset);  //获取端口号之前的域名  return index !== -1    ? host.substring(0, index)    : host;});//已废弃defineGetter(req, 'host', deprecate.function(function host(){  return this.hostname;}, 'req.host: Use req.hostname instead'));//请求是否的响应是否新鲜的defineGetter(req, 'fresh', function(){  //请求方法  var method = this.method;  //响应  var res = this.res  //状态码  var status = res.statusCode  //get、head方法不进行验证,因为他们是幂等的  if ('GET' !== method && 'HEAD' !== method) return false;  //状态码在200到300之间,或者304  if ((status >= 200 && status < 300) || 304 === status) {    //调用库来验证    return fresh(this.headers, {      'etag': res.get('ETag'),      'last-modified': res.get('Last-Modified')    })  }  //其他的状态码都不是新鲜的  return false;});//请求是否是陈旧的defineGetter(req, 'stale', function stale(){  return !this.fresh;});//请求是否是ajax请求defineGetter(req, 'xhr', function xhr(){  //获取头信息来判断  var val = this.get('X-Requested-With') || '';  return val.toLowerCase() === 'xmlhttprequest';});//帮助函数,创建getter函数function defineGetter(obj, name, getter) {  Object.defineProperty(obj, name, {    configurable: true,    enumerable: true,    get: getter  });}

 

这个原型对象继承了node原生的IncomingMessage,在express方法中创建,并且作为app.request属性,最后在init中间件中被req参数继承

转载地址:https://blog.csdn.net/qq_27868061/article/details/79250143 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:express之response.js
下一篇:express之全局中间件query

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年11月21日 01时05分12秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

光伏机器人最前线_华师大研发种树机器人 种植效率提高100倍以上 2019-06-17
jeecgboot 前端环境搭建_Jenkins +nginx 搭建前端构建环境 2019-06-17
跑带宽度多少合适_家用跑步机尺寸一般是多少 2019-06-17
zookeeper 进入客户端_Zookeeper客户端使用与集群原理 2019-06-17
回归标准差和残差平方和的关系_毕业论文中,回归分析中15个统计量解释 2019-06-17
异步任务_Spring Boot如何高效实现异步任务 2019-06-17
结束时间要大于开始时间_“吃鸡”体验服延长开服时间,SS5赛季结束时间会再度延长吗?... 2019-06-17
怎么跳转到源代码_程序员怎么快速接手一个项目 2019-06-17
战队不显示名字了_《新天龙八部》巅峰预选赛13大阵容分析有你心仪的战队吗?... 2019-06-17
jsp 上传转码_最完整的处理jsp处理乱码问题步骤,不需要手工转码 2019-06-17
python统计函数库_python统计函数库scipy.stats的用法1/3 2019-06-17
php 复制文件夹并压缩到最小_php 压缩文件夹 2019-06-17
delphi如何让窗口不获取焦点_三国志战略版有哪些隐藏技巧,高战如何能够好不费力获取海量战功... 2019-06-17
fifo页面置换算法设计思路_说说限流算法与设计思路 2019-06-17
lr检查磁盘时出错_win7系统提示数据错误循环冗余检查如何解决【教程】 2019-06-17
mysql 执行错误1395_主义 - 常规错误:1395无法删除连接视图 2019-06-17
如何安装mysql5.6实例_安装mysql5.6和多实例配置 2019-06-17
.frm mysql_mysqlfrm使用 2019-06-17
mysql数据库增加一行_在数据库中添加一行的SQL语句怎么写? 2019-06-17
mysql 获取备注_java 如何获取 mysql 备注信息 2019-06-17