当前位置: 首页 > 编程日记 > 正文

Express4.x API (四):Router (译)

Express4.x API 译文 系列文章

  • Express4.x API (一):application (译) -- 完成
  • Express4.x API (二):request (译) -- 完成
  • Express4.x API (三):Response (译) -- 完成
  • Express4.x API (四):router (译) -- 完成

已经完成了Express4.x API中的Requst和Response对象的文档翻译。简单的总结,request对象即表示HTTP请求,包含了请求查询字符串,参数,内容,HTTP头等属性;response对象则表示HTTP响应,即在受到请求时向客户端发送的HTTP响应数据。Express则基于此提供给我们一些方法,完成指定的请求和响应。

技术库更迭较快,很难使译文和官方的API保持同步,我们只有提升自己的英语能力才能更快的适应库的更新迭代,阅读到最新资料。
所以我此次翻译的目的,一是熟悉express文档,二是锻炼自己英语阅读能力;

原文地址:express.com

Router

router对象是中间件和路由的隔离实例,你可以把它看做一个仅能执行中间件和路由功能的mini-applaction,每一个Express应用程序实例都有一个内置的路由器

路由器的行为类似于中间件本身,所以你可以把他作为一个参数传递给app.use()或者作为参数传递给另一个路由器的use()方法。Express top-level 对象有一个Router()创建一个新的路由器对象

Properties

Router([options])

创建一个新的路由器对象

var router = express.Router([options]);

可选择的options参数指定路由器的行为

PropertyDescriptionDefault
caseSensitive是否启用大小写敏感默认情况下不敏感,以相同的方式对待"/Foo","/foo"
mergeParams从父路由器保存req.params值,如果子父有冲突的参数名称,以子路由参数优先false
strict启用严格路由默认情况下是禁用的,"/foo"和"/foo/"是相同的

你可以像应用程序那样添加中间件和HTTP方法路由(例如get,put,post等等)

// 调用传递给次路由的任何请求
router.use(function(req,res,next){// 一些逻辑,和其他中间件一样next();
})// 将会处理任何以/events结束的请求
router.get('/events',function(req,res,next){// ..
})

然后你可以为你特定的URL使用路由器,用这种方式把你的routes分为文件甚至是mini-apps

app.use('/calendar',router);

Methods

routers.all(path,[callback,...] callback)

这个方法就像router.METHHOD(),除了他匹配所有的HTTP方法

这个方法对于映射特定路径前缀或任意匹配的"全局"逻辑非常有用。举个栗子,如果你将以下路由置于所有路由的最前面,它要求从该点的所有路由都需要身份认证,并自动加载user。记住这些回调函数不必作为终点,loadUser可以执行任务,然后通过next()传递继续匹配给后续的路由

router.all('*',requireAuthentication,loadUser);

等价于

router.all('*',requireAuthentication)
router.all('*',loadUser)

另一个例子是white-listed"global"功能,这里的例子非常的相似,但是它只限制路径的前缀"/api"

router.all('/api/*',requireAuthentication);

router.METHOD(path,[callback,...] callback)

router.METHOD()方法在Express中提供路由功能,其中METHOD是HTTP方法之一,例如GET,POST,PUT等等,当然你可以小写。所以实际的方法是router.get()router.post()router.put()等等

router.get()函数将会自动的调用HTTP HEAD方法,除了router.head()router.get()之前要求没有走这条路

你可以提供多个回调,每个回调都被平等对待,表现的就像中间件,除了这些回调函数可以调用next(route)绕过其余路由回调。您可以使用此机制在路由上执行预条件,然后在没有理由继续匹配路由的情况下将控制传递给后续路由。

下面片段展示了最简单的路由定义,Express将字符串转化为正则表达式,在内部用于匹配传入请求。执行这些匹配时不考虑查询字符串,例如'GET'将匹配下面路由,像GET/?name='tobi'

router.get('/',function(req,res){res.send('hello world')
})

如果你有非常具体的约束条件,还可以使用正则表达式。举个栗子下面将会匹配"GET /commits/71dbb9c"以及 "GET /commits/71dbb9c..4c084f9".

router.get(/^\/commits\/(\w+)(?:\.\.(\w+))?$/,function(req,res){var from = req.params[0];var to = req.params[1] || 'HEAD';res.send('commit range' + form + '..' + to);
})

router.param(name, callback)

添加回调触发到路由参数中,name是参数的名称,callback是回调函数。虽然name在技术上是可选的,但是从Express v4.11.0没有它是不推荐使用这种方法的(如下)

  • req,请求对象
  • res,响应对象
  • next,指示下一个中间件的功能
  • name参数的值
  • 参数的名称

不像app.param(),router.param()不接受数组参数

举个栗子,当:user在路由路径中存在时,可以将用户加载映射为自动提供req.user给这个路由,或者执行验证的参数输入

router.param('user',function(req,res,next,id){//尝试从用户模型获取用户详细信息并将其附加到请求对象User.find(id,function(err,user){if(err){next(err);}else if(user){req.user = user;next();}else{next(new Error('fail to load user'))}}) 
})

该回调方法是在本地路由器上定义他们,它们不是由加载的应用程序或路由器继承的。因此,定义在路由上的参数回调只有通过router定义的路由参数才会触发

一个回调参数将被称为一次请求响应周期,即使参数在多个路径中匹配,如下面的栗子所示:

router.param('id',function(req,res,next,id){console.log('CALLED ONLY ONCE');next();
})router.get('/user/:id',function(req,res,next){console.log('although this matchs ');next();
})router.get('/user/:id',function(req,res){console.log('and this matchs too ');res.end();
})

将会依次打印:

CAALED ONLY ONCE
although this matchs
and this matchs too

以下部分描述router.param(callback)在v4.11.0将是过时的

router.param(name,callback)方法的行为通过仅传递一个函数到router.param()将会完全改变。此功能是如何实现router.param(name,callback)的习惯-它接受两个参数,必须返回一个中间件

函数返回的中间件决定了URL参数被捕获时发生的行为

在下面这个例子中,router.param(name,callback)签名被修改为router.param(name, accessId)router.param()将会接受一个name和一个number而不是一个name和一个回调函数`

var express = require('express');
var app = express();
var router = express.Router();// 定制 `router.param()`的功能
router.param(function(param,option){return function(req,res,next,val){if(val == option){next();}else{res.sendStatus(403);}}
})// 使用定制的`router.param()`
router.param('id',1337);// 触发捕获的路由
router.get('/user/:id',function(req,res){res.send('OK')
})app.use(router);app.listen(3000,function(){console.log('Ready');
})

在这个栗子中,router.param(name,callback)签名是相同的,但不是一个中间件回调,一个自定义检查函数定义了验证用户ID


router.param(function(param,validator){return function(req,res,next,val){if(validator(val)){next();}else{res.sendStatus(403)}}
})router.param('id',function(candidate){return !isNaN(parseFloat(candidate)) && isFinite(candidate)
})

router.route(path)

返回单个路由的实例,您可以使用可选中间件来处理HTTP verbs,使用router.route()为了避免重复路由命名,从而键入错误。

在上面router.param()栗子的基础上,下面的栗子展示了如何使用router.route()指定HTTP处理方法

var router = express.Router();router.param('user_id',function(req,res,next,id){// 示例用户,可能实际将从db等获取req.user = {id:id,name:'TJ'};next();
})router.route('/users/:user_id')
.all(function(req,res,next){// ..next()
})
.get(function(req,res,next){res.json(req.user)
})
.put(function(req,res){req.user.name = req.params.name;// 保存用户等res.json(req.user) 
})
.post(function(req,res,next){next(new Error('not implemented'));
})
.delete(function(req,res,next){next(new Error('not implemented'))
});

这个方法再利用单一/users/:user_id路径并且为各种HTTP方法添加处理程序

router.use([path], [function, ...] function)

使用指定中间件函数或者函数,可选的参数是挂载路径,默认是"/"

这个方法类似于app.use()。下面展示了一个简单的示例和用例:

中间件就像是管道,请求在第一个中间件函数定义时开始,并为它们"向下"匹配每一条路径处理中间件堆栈处理。

var express = require('express');
var app = express();
var router = express.Router();router.use(function(req,res){console.log('%s %s %s',req.method,req.url,req.path);next();
})// 下面只有当路径从挂载点开始时,才会调用这个函数
router.use('/bar',function(req,res,next){// ..next();
})// 总是调用
router.use(function(req,res,next){res.send('Hello world')
});app.use('/foo',router);app.listen(3000);

“挂载”路径被剥离并且对中间件功能不可见。这个功能的主要作用是:不管它的"prefix前缀"路径,安装中间件功能可能没有代码的变化

为了保证您使用router.use()定义的中间件的重要性。他们按顺序调用,因此顺序定义中间件优先级。举个栗子:通常logger是您将使用的第一个中间件,因此每个请求都会被记录

var logger = require('morgan');router.user(logger());
router.use(express.static(__dirname+'/public'));
router.use(function(req,res){res.send('hello')
})

现在假设您忽略了对静态文件的日志请求,但是在logger()之后要继续记录路由和中间件定义。你只需简单的移动express.static()到顶部,在添加日志中间件之前即可。

router.use(express.static(__dirname + '/public'));
router.use(logger());
router.use(function(req,res){res.send('Hello')
})

另一个例子是从多个目录中服务文件,给予"/public"优先

app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/files'));
app.use(express.static(__dirname + '/uploads'));

router.use()方法也支持命名参数,这样,其他路由器的挂载点可以通过使用命名参数预加载来获益。

NOTE:虽然这些中间件功能是通过特定路由器添加的,当他们运行时由他们连接到的路径来定义(而不是路由)。因此,如果路由器的路由匹配,则通过一个路由器添加的中间件可以运行其他路由器。举个栗子,下面显示安装在同一路径上的两个不同的路由器:

var autoRouter = express.Router();
var openRouter = express.Router();autoRouter.use(require('./authenticate').basic(usersdb));autoRouter.get('/:user_id/edit',function(req,res,next){// .. 编辑用户界面 .. 
})
openRouter.get('/',function(req,res,next){// .. 用户列表 ..
})
openRouter.get('/:user_id',function(req,res,next){// .. 查看用户 .. 
})app.use('/users',authRouter);
app.use('/users',openRouter);

尽管authenticate中间件是通过autoRouter路由加入的,但是它也将运行在openRouter定义的路由上,因为两个路由器都挂载在/users。为了避免这种行为发生,为每个路由器使用不同的路径。

写在后面

Express文档中Router部分就完成了,本人学识有限,难免有所纰漏或者理解不当之处,翻译仅仅是方便个人学习交流使用,无其他用意,原文地址:expressjs.com

转载于:https://www.cnblogs.com/okaychen/p/8093717.html

相关文章:

JavaScript(转载)

正则表达式用于字符串处理,表单验证等场合,实用高效,但用到时总是不太把握,以致往往要上网查一番。我将一些常用的表达式收藏在这里,作备忘之用。 匹配中文字符的正则表达式: [\u4e00-\u9fa5]匹配双字节字符…

复杂JSON参数传递后台处理方式

如图 或者使用 requestBoby 注解

shift()函数

用于对dataframe中的数整体上移或下移, 当为正数时,向下移。 当为负数时,向上移。 缺少的会填充NaN 参考: https://blog.csdn.net/kizgel/article/details/78333833 转载于:https://www.cnblogs.com/xxswkl/p/10831152.html

linux系统管理学习笔记之三----软件的安装

linux系统管理学习笔记之三----软件的安装 2009-12-29 19:10:02标签:linux 系统管理    [推送到技术圈] 版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。htt…

Vue+element UI实现“回到顶部”按钮组件

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/caomage/article/details/85006973 背景 开发框架是vuewebpackelement-ui&#xff0c;需要一个回到顶部的通用组件。 开发 HTML部分 code&#xff1a; <template><t…

根据xml 文件生成 xsd文件 以及相关测试方法

1、下载trang.jar 下载地址&#xff1a; http://www.java2s.com/Code/Jar/t/Downloadtrang20091111jar.htm 2、用法介绍 将trang.jar 包 和xml 文件放到同一个目录下 执行以下命令 java -jar trang.jar a.xml a.xsd 3、测试类 public class CheckXML {public static voi…

十一运夺金基础数据采集工具

点击下载 转载于:https://www.cnblogs.com/JiangHuakey/archive/2010/11/17/1880139.html

[HNOI 2010]Bounce 弹飞绵羊

Description 某天&#xff0c;Lostmonkey发明了一种超级弹力装置&#xff0c;为了在他的绵羊朋友面前显摆&#xff0c;他邀请小绵羊一起玩个游戏。游戏一开始&#xff0c;Lostmonkey在地上沿着一条直线摆上n个装置&#xff0c;每个装置设定初始弹力系数ki&#xff0c;当绵羊达到…

WordPress首页调用QQ签名

我的博客&#xff1a;http://Yourtion.TK 看到我的博客的朋友一定注意到我的页面旁边一个QQ签名的实时显示&#xff0c;如下图&#xff1a; 是怎么实现的呢&#xff1f;&#xff1f;下面一步步告诉你。希望对你有帮助。 首先登陆QQ滔滔首页&#xff1a;http://www.taotao.com/并…

断网,启用网络,关机的实现。

windows 下实现 shutdown_two.c 此为第三版 // 我需要一个断开网络&#xff0c;启用网络&#xff0c;定时发送邮件后关机的功能&#xff0c;其中定时发送邮件功能是邮件客户端完成&#xff1b;原来的工具是用bat实现的&#xff0c;后来给BAT内容放到C中&#xff0c;延时部分用…

BaseTDI.sys 瑞星卡巴冲突,导致机器蓝屏

今天中午在给本次评教活动导入各学院10级学生信息时&#xff0c;多次出现蓝屏&#xff0c;其主要错误信息为 “BaseTDI.SYS Address 9188783F base at 91887000 Data Stamp 45a47636”.并且 提示“crash dump …..&#xff08;系统崩溃&#xff09;”. 于是&#xff0c…

【22,23节】Django的GET和POST属性笔记

COOKIES&#xff1a;一个标准的python字典对象&#xff0c;包含所有cookies&#xff0c;键和值都为字符串session&#xff1a;一个即能读又能写的类似字典对象&#xff0c;表示当前的会话&#xff0c;只有当django启用会话的支持时才可用 一键多值的GET[]只能接收到最后一个值&…

dataTable 表格组件刷新 问题记录

1 、 重绘 使用fnDraw() 进行刷新表格使用的前体是开启了服务端分页和查询时使用此进行刷新表格 fnDraw(boolean)true : 表示整体刷新 且刷新后 到起始页 false &#xff1a; 刷新后在刷新前的页 2、 $(#confess-table-info).DataTable().ajax.reload()重绘 使用此方法进行…

旺铺免费,淘宝的义务不能免

旺铺免费&#xff0c;淘宝的义务不能免阿祥春节前夕&#xff0c;淘宝网免费开放“旺铺扶持版”&#xff0c;降低创业门槛&#xff0c;希望帮助更多中小卖家快速成长。从大道理上讲&#xff0c;旺铺免费&#xff0c;是淘宝所承担的社会责任&#xff0c;既为政府分忧&#xff0c;…

下载安装 binary editor

http://www.eecanalyzer.net/downloads 转载于:https://www.cnblogs.com/sea-stream/p/10842190.html

使用Mpvue 使用 scroll-view 记录以及 页面设置弹窗后 页面滚动问题

1、scroll-view 使用 <scroll-view scroll-y"true"class"msg-list"scrolltolower"scrolltolower"scroll"scroll"> </scroll-view> methods: {scrolltolower(){console.log(7)},scroll(e) {console.log(6)console.log(e…

YOLOv10环境搭建、模型预测和ONNX推理

运行后会在文件yolov10s.pt存放路径下生成一个的yolov10s.onnxONNX模型文件。安装完成之后,我们简单执行下推理命令测试下效果,默认读取。终端,进入base环境,创建新环境。(1)onnx模型转换。

时间不同单位之间的转换

在观察仿真波形的时候&#xff0c;经常会出现微妙&#xff0c;毫秒&#xff0c;皮秒之间的转换&#xff0c;出现过错误&#xff0c;每次记不清楚的时候还要重新查资料&#xff0c;现总结如下. 秒&#xff08;second&#xff09;是国际单位制中时间的基本单位&#xff0c;符号是…

关于Javascript的内存泄漏问题的整理稿

常规循环引用内存泄漏和Closure内存泄漏 要了解javascript的内存泄漏问题&#xff0c;首先要了解的就是javascript的GC原理。 我记得原来在犀牛书《JavaScript: The Definitive Guide》中看到过&#xff0c;IE使用的GC算法是计数器&#xff0c;因此只碰到循环 引用就会造成mem…

C#计算两个日期的相隔天数

DateTime start Convert.ToDateTime(dateStart.ToShortDateString()); DateTime end Convert.ToDateTime(dateEnd.ToShortDateString()); TimeSpan sp end.Subtract(start); int days sp.Days;转载于:https://www.cnblogs.com/weimingxin/p/8109234.html

.NET 端口监听

1.直接调用微软socket对象处理 static void Main(string[] args){try{IPAddress ip new IPAddress(new byte[] { 127, 0, 0, 1 });//在3721端口新建一个TcpListener对象TcpListener listener new TcpListener(ip, 3721); listener.Start();Console.WriteLine("started l…

微信小程序导航栏设置透明

使用的时Mpvue 在app.json 文件中设置 "window": {"navigationStyle": "custom"},

epub 电子书软件代码销售

epub 电子书软件代码销售本套代码用来读取epub 格式电子书。主要面向&#xff1a;有一定开发能力的人员&#xff0c;和有一定制作水平的朋友们。用途&#xff1a;自己开发学习&#xff0c;钻研&#xff0c;出appstore 应用&#xff0c;卖钱&#xff0c;加广告赚钱等。&#xff…

重新编译iptables

重新编译iptables一&#xff0e;重新编译后的内核版本为&#xff1a;<?xml:namespace prefix st1 ns "urn:schemas-microsoft-com:office:smarttags" />2.6.28.10重新编译后的iptables的版本为&#xff1a;1.4.4&#xff0c;新添加了layer7的模块&#xff0…

爬虫之Xpath详解

爬虫之Xpath详解 XPath介绍 XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。 XPath 是 W3C XSLT 标准的主要元素&#xff0c;并且 XQuery 和 XPointer 都构建于 XPath 表达之上。 因此&#xff0c;对 XPath 的理解是很多高级 XML 应…

非常认同的《SEO优化大全》

1、每个网页标题简洁&#xff0c;不超过30字。  2、每个网页核心关键词不超过3个。如果可以&#xff0c;你要学会放弃。  3、最重要的关键词放在标题首位&#xff0c;依次类推。  4、网站的描述&#xff0c;简洁&#xff0c;明了&#xff0c;最开始和结束部分自然出现关键…

python中tornado的第一个例子

python中tornado的第一个例子 1 先安装tornado pip install tornado 2 新建tor.py 记住不能建立 tornado.py 这样的名字 不然会报错 ImportError: No module named tornado.ioloop; tornado is not a package import tornado.ioloop import tornado.webclass MainHandler(tor…

docker 安装和使用

目录 1、安装docker的官方网站 配置镜像加速器 查看docker安装的版本 重启docker 启动 docker 查看启动的状态 下载测试镜像 并且启动该容器 2、操作docker 镜像的常用命令 搜索镜像 下载镜像 列出镜像 删除本地镜像 保存镜像到本地 加载镜像到docker仓库 构…

不编译内核加载connlimit模块

转载于:https://blog.51cto.com/sookk8/280372

记录一下g++的编译选项

假设main.cpp,hello.h,hello.cpp,其中main.cpp调用了hello类中的方法 1 生成hello.so g -shared hello.cpp -olibhello.so 2 编译main.cpp,并链接,并指定运行时libhello.so的位置 g main.cpp -lhello -L./ -Wl,-rpath./ -o main 值得一提的是,如果采用带版本号的库,例如libhell…