【问题标题】:Is the Regex right against what am I trying to do?正则表达式对我想要做什么是正确的吗?
【发布时间】:2012-07-18 14:48:22
【问题描述】:

我正在创建一个可重用的 node.js NavigationController 类,以便我可以在其他服务器端项目中重用它,如果我可能需要或其他人可能会觉得它有用。

这是用例。

var navController = new NavigationController({
    routes : {
        '/user/:action/:anything' : 'UserController',
        '/app/:action' : 'AppController',
        '/file/:action' : 'FileController',
        '/feedback/:action' : 'FeedbackController',
        '/:anything' : 'ErrorController'
    },
    ErrorController : 'ErrorController'
});
navController.init();

用户根据服务器请求可以调用该对象的这个函数。

navController.navigate(req, res);

现在 this 和控制器被正确调用了。 navigate(req, res) 函数下的东西,它是基于 URL 调用适当的控制器对象的一部分,被定义为名为 getRouteByPath(path) 的函数。此私有函数将获取路由并允许 navigate(req, res) 函数获取要调用的控制器类名称。

var getRouteByPath = function(path) {
    for(var route in config.routes) {
        var routeRegex = '';

        var routeParts = route.split('/');

        for(var rp = 0; rp < routeParts.length; rp++) {

            // checking if route part starts with :
            if(routeParts[rp].indexOf(':') === 0) {

                // this is "anything" part
                routeRegex += '[/]?([A-Za-z0-9]*)';

            } else if(routeParts[rp] != "") {
                routeRegex += '[/]?' + routeParts[rp];
            }
        }

        var routeRegexResult = path.match(routeRegex);
        if(routeRegexResult) {
            console.log(routeRegexResult);
            return route;
        }
    }
    return null;
};

我太担心这个功能,好像这是正确的方法?

【问题讨论】:

  • 这个问题属于codereview.stackexchange.com
  • 根据在适当网站上发布问题的定义,StackOverflow 应该只有与溢出的堆栈相关的问题:)

标签: javascript regex node.js webserver


【解决方案1】:

一些缺陷:

  • 为什么使用斜杠作为字符类 ([/])?无需这样做,仅在正则表达式文字中您需要使用反斜杠(如/\//g)对其进行转义。只需使用单个“/”代替 (new RegExp("/", "g"))。

  • .indexOf(&lt;string&gt;)==0 确实有效,但搜索整个字符串并且效率不高。最好使用startswith,在你的情况下使用routePart.charAt(0)==":"

  • &lt;string&gt;.match(&lt;string&gt;) - 我建议构建一个新的RegExp object 并使用.test,因为您不想匹配 - 也不需要构建捕获组,我认为,因为您只返回路由字符串但没有匹配(好的,您记录它们)。

  • 您想检查整个path 是否与您的正则表达式匹配?不要忘记添加^$。您当前的 AppController 正则表达式也匹配 /user/app/example 之类的路由。

  • 为什么你的斜线(并且只有斜线)是可选的(/?)?不仅我认为这不是您想要的,而且在构建像 /\/?user\/?([A-Za-z0-9]*)\/?([A-Za-z0-9]*)/ 这样的正则表达式时,它也打开了通往 catastrophic backtracking 的大门

    要避免这种情况,您需要将整个组设为可选:(?:/([^/]*))?

  • 此外,您应该只构建一次正则表达式(在初始化时)并将它们存储在缓存中,而不是每次调用 getRouteByPath 时都构建它们。 RegExp 的编译隐藏在您的代码中,尽管它需要发生。

【讨论】:

  • 这里不要使用exec,使用RegExp.prototype.test。另外routePart.indexOf(':') == 0 最好写成routePart.charAt(0) == ':'
  • 谢谢,这正是我的意思 :-) 还要添加 indexOf 的东西
  • [/]?是否存在,因为如果定义的路由类似于 /user/:action/:anything 并且用户请求 URL /user/me 或 /uer/me/you,则将在两个请求中调用控制器。这不是正常的做法吗?
  • 您也能解释一下这一点吗? “你为什么使用斜杠 (/) 作为字符类?不需要这样做,只有在正则表达式中你需要用反斜杠转义它。”
  • 每次使用字符串调用match 都会创建一个,并且尽管是相对大量的计算,但您的代码中不会注意到“编译”。另请参阅我的最后一点
【解决方案2】:

几点说明:

routeRegex += '[/]?([A-Za-z0-9]*)';

表示路由可能存在也可能不存在// 将匹配可能+* 更适合。

另外,因为我瘦了_ 在网络路由中是允许的

您的.split('/'),将从路由中删除所有/,因此它不应该在拆分列表中

【讨论】:

  • [/]?是否存在,因为如果定义的路由类似于 /user/:action/:anything 并且用户请求 URL /user/me 或 /uer/me/you,则将在两个请求中调用控制器。这不是正常的做法吗?
  • 是的,我的大脑审查了你将它们全部附加在一起的事实,[/]? 说它可能存在也可能不存在,我们不总是希望它存在吗?
猜你喜欢
  • 1970-01-01
  • 2013-04-07
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多