不知道有没有人碰到我这种问题的,express router非常灵活,但用于构造REST路径,尤其是大批量的书写REST路径挺麻烦的,对于复杂的路径,一个正则写两三行也是有的,每次修改一次规则,真的要晃了眼。我在实际项目中有类似这种需求:当指定了from的值时,to才可以指定值,filter是可以省略的,但省略filter则from和to都得省略,比如:
/article/category/:category+/filter/:filter(id|date)/from/:from/to/:to/list/:page?
如果用express router来做这个的话就非常麻烦了,上述路由要达到需求,不辅助其它函数是无法完成的,不过如果直接写正则是可以完成的,比如:
/^\/article\/category((?:\/\d+)+)(?:\/filter\/(id|date)(?:\/from\/(\d+)(?:\/to(?:\/(\d+)?)?)))?\/list(?:\/(\d+)?)?$/i
写出来没问题,修改的时候就想哭了,所以有了写这个模块的想法(上面的正则是由这个模块生成的)。先说一下使用本模块简化后的路由:
/article/:category+/#filter(id|date)/+from/+to?/:list<page>?
匹配
/article/category/1/2/list /* {category: "1/2"} */
/article/category/1/2/filter/id/from/2/list/2 /* {category: "1/2", filter: "id", from: 2, page: 2} */
/article/category/1/2/filter/id/from/2/to/3/list/2 /* {category: "1/2", filter: "id", from: 2, to: 3, page: 2} */
不匹配
/article/category/1/2/from/2/to/3/list/2
/article/category/1/2/to/3/list/2
如果把一个router path按slash分成段的话,每一段的规则是:
/[prefix] name [(rule)] [<alias>] [suffix]
- prefix 前缀
- 静态
<empty>
- 不可省略
:
- 可省略
#
- 必须跟随前段,不可省略
+
- 必须跟随前段,可省略
*
- 静态
- suffix 后缀
- 单项值匹配
<empty>
- 多项值匹配
+
- 可选的,单项值匹配
?
- 可选的,多项值匹配
*
- 单项值匹配
- name 段名
- rule 正则表达式规则
- alias 别名
别名规则 比如:
router: /article/:list<page>?
GET /article/list/1
得出的结果是:
req.params = {
page: 1
}
rule正则
router: /:article<id>
默认匹配/article/\d+
如果要修改匹配规则,比如,只允许2位数字,可以这样:/:article(\d{2})<id>
或者对于比较复杂的正则,可以不写在路由表达式内,下面给出一个完整的例子
var express = require('express');
var Router = express.Router;
var RestRouter = require('express-rest-router');
var router = Router();
var restRouter = RestRouter();
router.get('/article/index.html', function (req, res) {
res.send('express 的router可以继续使用');
});
restRouter.get('/article/#filter(date|id)/+from/*to/:list<page>?.html', function(req, res) {
// 'restRouter也可以共存,用法和express.router相同'
res.send(req.params);
res.end();
});
restRouter.get({
path:'/product/#filter/+from/*to/:list<page>?.html'
rules:{
filter: 'date|id',
}
}, function(req, res) {
// '这里用法稍有不同'
res.send(req.params);
res.end();
});
var app = express();
app.use(router);
app.use(restRouter);
app.listen(3000, function(){
console.log('listen on 3000');
});
基于这个路由转正则的模块,只替换掉了express router原先的依赖项path-to-regexp
,并非fork express所以用法和express.router是兼容的。
附两个模块npm
rest-to-regexp
express-rest-router