express.js路线说明

far*_*jad 9 javascript regex node.js express

我正在查看源代码,以了解它如何将命名的路由参数映射到req.params属性.

对于那些不知道的人,在express.js中你可以用命名参数定义路由,使它们成为可选的,只允许具有特定格式的路由(以及更多):

app.get("/user/:id/:name?/:age(\\d+)", function (req, res) {
    console.log("ID is", req.params.id);
    console.log("Name is", req.params.name || "not specified!");
    console.log("Age is", req.params.age);
});
Run Code Online (Sandbox Code Playgroud)

我意识到这个功能的核心是一个pathRegexp()lib/utils.js中定义的方法.方法定义如下:

function pathRegexp(path, keys, sensitive, strict) {
    if (path instanceof RegExp) return path;
    if (Array.isArray(path)) path = '(' + path.join('|') + ')';
    path = path
        .concat(strict ? '' : '/?')
        .replace(/\/\(/g, '(?:/')
        .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function (_, slash, format, key, capture, optional, star) {
            keys.push({ name: key, optional: !! optional });
            slash = slash || '';
            return ''
                + (optional ? '' : slash)
                + '(?:'
                + (optional ? slash : '')
                + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')'
                + (optional || '')
                + (star ? '(/*)?' : '');
        })
        .replace(/([\/.])/g, '\\$1')
        .replace(/\*/g, '(.*)');
    return new RegExp('^' + path + '$', sensitive ? '' : 'i');
}
Run Code Online (Sandbox Code Playgroud)

重要的部分是第7行的正则表达式,/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g它以这种方式对路径名的匹配部分进行分组:

slash     the / symbol                                                                                                                    

format   I don't know what is the purpose of this one, explanation needed.                                    

key       the word (ie. \w+) after the : symbol                                                                           

capture a regex written in front of the key. Should be wrapped in parenthesis (ex. (.\\d+))

optional the ? symbol after the key                                                                                            

star       the * symbol                                                                                                                     

并且回调处理程序从上面的组构建一个正则表达式.


现在的问题是,format这里的目的什么?

我的理解如下:

(format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)'))
Run Code Online (Sandbox Code Playgroud)

和前面提到的正则表达式是,

如果您.slash组后面放置一个符号并且未指定匹配条件(正则表达式包含在括号后面key),则生成的正则表达式匹配其余部分,path直到它到达./符号.

那有什么意义呢?


我问这个,因为:

  1. 我想在我的应用程序中提取和使用此方法,并希望在使用它之前完全理解它的工作原理.
  2. 我没有在express.js上找到任何关于它的文档.
  3. 我只是好奇 :)

log*_*yth 5

它适用于匹配文件扩展名等.

给定路径'/path/:file.:ext',考虑表达式之间的差异:

// With 'format' checking
/^\/path\/(?:([^\/]+?))(?:\.([^\/\.]+?))\/?$/

// Without 'format' checking
/^\/path\/(?:([^\/]+?))(?:([^\/]+?))\/?$/
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,你最终得到了params

{
    file: 'file',
    ext: 'js'
}
Run Code Online (Sandbox Code Playgroud)

但没有格式检查,你最终得到这个:

{
    file: 'f',
    ext: 'ile.js'
}
Run Code Online (Sandbox Code Playgroud)