为具有可变数量参数的Express路由编写正则表达式

时间:2017-04-11 19:06:57

标签: regex express

我正在构建API,并尝试允许用户过滤'使用任何参数组合的结果集。

我们有2只猫,每只有4个属性:名称年龄性别颜色。< / p>

cat1 = {'name': 'Fred', 'age': '10', 'sex': 'male', 'color': 'white'}

cat2 = {'name': 'Alex', 'age': '10', 'sex': 'male', 'color': 'black'}

我希望单一路由匹配用户选择应用于其搜索的参数的任意组合。例如,路线将匹配以下(以及任何其他组合):

router.get('/name/:name/age/:age/sex/:sex/color/:color', ...){}

router.get('/name/:name/age/:age/sex/:sex', ...){}

router.get('/age/:age/color/:color', ...){}

基本上,所有参数都是可选的。

我认为正则表达式是最好的方法 - 我怎么能这样做?

1 个答案:

答案 0 :(得分:1)

执行此操作的方法是使用正则表达式来解析完整URI并提取搜索条件。 标准订单是免费的。

要提取参数的值,我使用以下正则表达式:

\/ paramName \/([^\/]+)(\/|$)

<强>解释

\/ paramName \/:在斜杠之间匹配给定的参数名称

([^\/]+):匹配斜线以外的任何内容(这是我们的值)

(\/|$):以斜线或行尾结束

这是一个有效的 JavaScript代码段

/**
* Extract the value of a param inside a path
* Path format should match this pattern : /p1/p1value/p2/p2Value/pX/pXValue
* @param {string} path The path
* @param {string} param The param name
*/
function getParamValue(path, param) {
  var re = new RegExp('\/'+ param + '\/([^\/]+)(\/|$)');
  var matches = re.exec(path);
  if(matches && matches.length) {
    return matches[1];
  }
}

// Define possible criteria
var criteria = ['name', 'age', 'sex', 'color', 'dummy'];

// Let's play with some sample paths
var paths = [
  "/name/mcfly/age/42/sex/male/color/blue",
  "/sex/male/name/color/blue/mcfly/age/42",
  "/sex/male",
  "/color/black/name/kitty"
];

// For each path, display criteria and associated values
paths.forEach(function(path) {
  console.log("path=", path);
  criteria.forEach(function(criterion) {
    console.log(criterion + '=' + getParamValue(path, criterion));
  });
  console.log("------------------------");
});

此外,还有一个示例 Express app:

<强> utils.js

module.exports = {
    getParamValue: function (path, param) {
      var re = new RegExp('\/'+ param + '\/([^\/]+)(\/|$)');
      var matches = re.exec(path);
      if(matches && matches.length) {
        return matches[1];
      }
    }
}

搜索-service.js

var utils = require('./utils');

module.exports = {
    getSearchCriteria: function(path) {
        var criteria = [];

        ['name', 'age', 'sex', 'color'].forEach(function(criterion) {
            var value = utils.getParamValue(path, criterion);
            if(value) {
                criteria.push({"criterion": criterion, "value": value});
            }
        });

        return criteria;
    },

    search: function(criteria) {
        return "search using the following criteria", JSON.stringify(criteria, null, 2);
    }
}

<强> app.js

var express = require('express');
var app = express();
var searchService = require('./search-service');

var port = 7357;

app.get('/api/search/*', function(req, res, next) {

    var criteria = searchService.getSearchCriteria(req.originalUrl);
    var result =   searchService.search(criteria);

    res.send("<!doctype html><html><body><pre>" + result + "</pre></body></html>");
});

// start server
app.listen(port, function() {
    console.log('Server listening on port %d', port);
});

运行node app然后测试一些网址:

http://localhost:7357/api/search/name/mcfly/age/42/sex/male/color/blue

http://localhost:7357/api/search/sex/female/color/orange/name/judith/age/25

http://localhost:7357/api/search/color/green

并检查页面内容