Express路由处理非ASCII字符(波斯语)

4
我尝试使用这个路由http://localhost:3030/api/words/عشق在我的express应用程序中,以便我可以匹配字典中的单词。
浏览器将url更改为http://localhost:3030/api/words/%D8%B9%D8%B4%D9%82,但是我编写了一个小型中间件,将其转换回原始版本,然后将其传递给路由。在路由中,我拥有检查波斯语/波斯语字符所包含的Unicode字符的正则表达式。
不确定发生了什么,因为中间件打印出/words/عشق,如果我删除正则表达式规则,路由也会打印出/words/عشق。为什么express无法匹配这个路由?express不使用req.url来确定路由吗?
    /** Get word be string **/
    api.get('/:word(^([\\u0600-\\u06FF]+\\s?)+$)', (req, res, next) =>{
            console.log("persian version " + req.url);
            res.send(req.params);
});


 /** Url encoder middleware **/ 
function urlencoder(req, res, next) {
      req.url = decodeURIComponent(req.url); 
      console.log("Middleware " + req.url);
      next();
}

我认为它不使用它。重写成那样也感觉不对。为什么不在您的api.get函数中解码它,然后再查找呢? - David
因为如果URL没有预解码,我就无法使用正则表达式匹配它。 - Yasin Yaqoobi
根据我对Express路由器的理解,修改req.url应该是可行的。那么api的定义是什么?以及在中间件堆栈中,api和urlencoder的位置在哪里呢? - PMV
是的,使用中间件来调整req.url的值确实有效 - 在中间件链中该点之后的所有路由都基于修改后的URL进行路由。 - PMV
我在 cors 中间件之后、body parser 之前添加了中间件。甚至关闭了其他中间件,但似乎没有起作用。该 API 是一个 Express 路由器,用于将路由分组到不同的类中。 - Yasin Yaqoobi
1个回答

2

我认为将路由路径转换为正则表达式的代码已经在正则表达式前添加了锚点(^),因此你不需要在自己的代码中再使用额外的锚点。

以下代码看起来应该可以正常工作:

let unescape = require('querystring').unescape;

api.use((req, res, next) => {
  req.url = unescape(req.url);
  next();
});

api.get('/:word(([\\u0600-\\u06FF]+\\s?)+$)', (req, res) => {
  console.log("persian version " + req.url);
  res.send(req.params);
});

2
我认为路由器不会自动在正则表达式前缀加上 ^,而是我认为这是对 ^ 意义的误解。^ 表示“字符串开头”或“行开头”,具体取决于多行标志。因此,在搜索一个字符串时,如果该字符串的开头在中间,则不会匹配任何可能的字符串(请注意,URL 从定义上来说是单行的,因此只能有一种解释 ^ 的含义)。 - slebetman
@slebetman 我认为我们的意思是一样的 :D 像 /:word 这样的路由路径将被转换为以 ^\/ 开头的正则表达式(后面跟着参数匹配)。因此,添加另一个 ^ 将永远无法匹配路径的开头。 - robertklep
@robertklep 不,我们的意思不一样。他的正则表达式是“:word^...” - 他试图匹配在任何字母数字字符之后开始的字符串。显然这永远不会匹配任何字符串,因为“开始”的定义意味着它之前不能有任何东西。这就像有人试图匹配正则表达式“.*$hello” - 一个在它结束之前就结束的字符串和一个在它开始之后开始的字符串一样愚蠢。 - slebetman
@slebetman :word 不是URL中要匹配的字面字符串,而是一个占位符,它会被Express翻译成特定的正则表达式模式(匹配一系列字母数字字符,我想)。您可以通过添加自己的正则表达式模式,使用:word(REGEX)来覆盖该占位符要匹配的模式。 - robertklep
@robertklep:是的,但^也不是一个字面字符串匹配。它表示“在此字符之前没有任何字符”- 也就是“字符串的开头”。因此,如果:word匹配了某些内容,那么在其后跟着^意味着^不能再是字符串的开头,因此正则表达式无法匹配任何可能的字符串。原始正则表达式能够工作的唯一可能方式是如果:word表示空字符串,但这不是它通常的含义。我假设它表示任何字母数字字符,而不是空字符串(如我在上面的评论中所说)。 - slebetman
@slebetman 我们两个都是对的:你是因为当已经有一个前缀要匹配时,锚定字符串的开头就没有意义了;而我是因为在正则表达式中使用两个 ^ 锚点也没有意义。 - robertklep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接