![Apache2:使用 RewriteCond 和 RewriteRule 匹配查询字符串中的重音字符时出现问题](https://linux22.com/image/800319/Apache2%EF%BC%9A%E4%BD%BF%E7%94%A8%20RewriteCond%20%E5%92%8C%20RewriteRule%20%E5%8C%B9%E9%85%8D%E6%9F%A5%E8%AF%A2%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E7%9A%84%E9%87%8D%E9%9F%B3%E5%AD%97%E7%AC%A6%E6%97%B6%E5%87%BA%E7%8E%B0%E9%97%AE%E9%A2%98.png)
正在开发一个网站,计划将 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
' 而不是 ' '。