Apache2:使用 RewriteCond 和 RewriteRule 匹配查询字符串中的重音字符时出现问题

Apache2:使用 RewriteCond 和 RewriteRule 匹配查询字符串中的重音字符时出现问题

正在开发一个网站,计划将 URL 从查询字符串格式转换为基于数字的格式。许多 URL 中都有未转义的重音字符和类似的 UTF8 字符。问题是什么?我似乎无法让 Apache2 正确匹配重音字符并进行重写。我正在 Apache2 配置中执行所有这些操作。

例如,此 URL:

http://great.website.example.com/?place=cafe

将按此 Apache2 RewriteRule 设置按预期工作:

  RewriteCond %{QUERY_STRING} ^(place|location)=cafe
  RewriteRule ^/find/$ /find/1234? [L,R=301]

现在查看此 URL。请注意重音符号é

http://great.website.example.com/?place=café

为什么该 URL 不适用于以下 Apache2 RewriteRule 设置:

  RewriteCond %{QUERY_STRING} ^(place|location)=café
  RewriteRule ^/find/$ /find/1234? [L,R=301]

这两条规则都应将 URL 重写为以下内容:

http://great.website.example.com/find/1234

但是带重音符号的例子é根本不起作用。也许通配符可以起作用,但我似乎也无法让它起作用。

答案1

您可以使用 RewriteMap 来为您执行非转义操作。就像这样:

RewriteMap unescape int:unescape

RewriteCond %{QUERY_STRING}  (location|place)=(.*)
RewriteCond ${unescape:%2}   café
RewriteRule ^/find/$         /find/1234? [L,R]

在第二个 RewriteCond 行中我使用 %2,因为 %1 包含“location”或“place”。

但是,为了将单词映射到数字而向配置中添加大量 RewriteRules 会严重影响服务器的性能,并且难以维护。更好的解决方案是也使用 RewriteMap。

例如,假设/etc/apache2/places.txt包含:

café    1234
shop   1235
...

那么这对你有用:

RewriteMap unescape int:unescape
RewriteMap places   txt:/etc/apache2/places.txt

RewriteCond %{QUERY_STRING}  (location|place)=(.*)
RewriteCond ${unescape:%2}   (.*)
RewriteRule ^/find/$         /find/${places:%1}? [L,R]

您还可以使用基于数据库查询的 RewriteMap。这是我的首选,因为我可以将单词与数字匹配的工作交给内容管理系统。

您可以在文档中找到更多详细信息: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewritemap

答案2

你的/?place=café意愿url 编码通过浏览器/?place=caf%C3%A9,这就是您应该匹配的。

答案3

在一个相关问题,有人建议使用RewriteMap调用外部程序来重写 URL。

另外:也许请求实际上是完全不同的东西?浏览器可能在内部将重音字符转换为 url 编码的 ASCII?例如 ' %20' 而不是 ' '。

相关内容