Express.js中Route Params的正则表达式

Chr*_*ing 2 node.js express

根据各种文档和博客,以及这个问题和其他问题,我知道可以使用正则表达式验证路由参数.然而,这让我找了大约一个半小时:

app.get('/api/:url(/^http:\/\/(.+?)\.(.+?)$/)', (req, res) => {
  // do stuff with req.params.url
});
Run Code Online (Sandbox Code Playgroud)

每当我在本地运行服务器并输入时localhost://8000/api/http://www.google.com,响应就是Cannot GET /new/http://www.google.com

我知道正则表达式做了我想要它做的事情,因为:

/^http:\/\/(.+?)\.(.+?)$/.test('http://www.google.com');
Run Code Online (Sandbox Code Playgroud)

...返回true.

我也试过改变路线字符串看起来像......

'/api/:url(^http:\/\/(.+?)\.(.+?)$)'

'/api/:url(http:\/\/(.+?)\.(.+?))'

'/api/:url/^http:\/\/(.+?)\.(.+?)$/'
Run Code Online (Sandbox Code Playgroud)

还有其他几种格式看起来像Stack Overflow线程和博客中给出的示例(Express文档绝对没有在第一个路径参数之外使用的正则表达式的示例).也许有一些我不知道的格式限制,或者Express中对RegExp支持的限制?如果文档说什么的话会很棒.

我感谢任何帮助.

小智 6

对于你想要实现的目标,你的正则表达式是错误的.

TL; DR使用这个:

app.get('/api/:url(https?:\/\/?[\da-z\.-]+\.[a-z\.]{2,6}\/?)', (req, res) => {
});
Run Code Online (Sandbox Code Playgroud)

一些解释:

首先,path-to-regexpexpress使用的模块正如其名称所说的那样:将路径转换为正则表达式.因此,这些^$锚点要么是非法的,要么在置于:url()内容中时可以被不同地解释(path-to-regexp已经使用它们).此外,不要在JavaScript中使用斜杠来标识RegExp对象,而只包括表达式内容.

以下是express查看正则表达式的方法:

path: '/api/:url(/^http://(.+?).(.+?)$/)'
regexp: /^\/api\/(?:(\/^http:\/\/(?:\.+?))\.(\.+?)$\/)\/?$/i

path: '/api/:url(^http://(.+?).(.+?)$)'
regexp: /^\/api\/(?:(^http:\/\/(?:\.+?))\.(\.+?)$)\/?$/i

path: '/api/:url(http://(.+?).(.+?))'
regexp: /^\/api\/(?:(http:\/\/(?:\.+?))\.(\.+?))\/?$/i

path: '/api/:url/^http://(.+?).(.+?)$/
regexp: /^\/api\/(?:([^\/]+?))\/^http:\/\/(?:\.+?)\.(\.+?)$\/?$/i
Run Code Online (Sandbox Code Playgroud)

并且,使用这样的代码片段,您可以看到没有匹配:

const url = 'http://www.google.com';
for (let layer of app._router.stack) {
  if (layer.name === 'bound dispatch') {
    console.log(layer.regexp + ': matches', url, '=', layer.regexp.test(url));
  }
}
Run Code Online (Sandbox Code Playgroud)

建议避免在已命名的捕获中使用捕获括号.

示例(注意URI方案周围的额外括号,以及它们如何更改req.params.url值):

app.get('/api/:url((https?:\/\/)?[\da-z\.-]+\.[a-z\.]{2,6}\/?)', (req, res) => {})

> req.params: { '0': 'http://', url: 'http://' }
Run Code Online (Sandbox Code Playgroud)

稍后编辑:请注意,这整篇文章仅涉及包含正则表达式的字符串路由,而不是使用RegExp对象定义的路由.