写了一个REST风格路由表达式转正则的包,另附基于这个包的express router
发布于 8 年前 作者 dashdots 4440 次浏览 来自 分享

不知道有没有人碰到我这种问题的,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

回到顶部