使用 nginx 和映射时,可以使用映射文件重写多个 URL。问题是当 URL 包含特殊字符时。我一直在绞尽脑汁试图解决这个问题,希望这个问题/解决方案可以让其他人免于白发苍苍。
让我们设定一下场景。
运行标准 nginx 的 Linux 服务器 (Debian/Ubuntu)。指向此服务器的 DNS 可解析为服务器配置。包含传入和传出 URL 的重复条目的 Map(可解析)
地图设置包含以下内容:
map $host$request_uri $rewrite_uri {
include /<path to file filename>;
}
地图文件本身每行包含一个条目,以分号结尾。
example.com/Böhme https://anotherexample.org/SomeWeirdPath/Böhme;
此映射工作的服务器配置
server {
listen 443 ssl http2;
ssl_certificate /<absolute path to crt file>;
ssl_certificate_key /<absolute path to key file>;
server_name example.com;
proxy_set_header X-Forwarded-For $remote_addr;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_dhparam <absolute path to Diffie Hellman key>;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
server_tokens off;
if ($rewrite_uri) {
rewrite ^ $rewrite_uri redirect;
}
rewrite ^ <default URL> redirect;
}
我简化了此服务器配置的配置,以便我们可以专注于地图设置。配置假定域将使用 SSL 并且证书有效。仅当 $host$request_uri 位于具有 $rewrite_uri 的列表中时,才会执行 if 语句,否则将执行最后一个重写。
问题
我该如何转换 $request_uri 以便 nginx 正确理解它?映射文件包含 UTF8 格式的值,但 nginx 似乎想要 URL 编码的 $request_uri 和十六进制格式。
$request_uri 与 mapfile 中的一样
example.com/Böhme
$request_uri 根据浏览器进行 URL 编码
example.com/B%C3%B6hme
$request_uri 因为我认为 nginx 需要它
example.com/B\xC3\xB6hme
我似乎找不到具有此功能的系统包,但我想我开始在这里重新发明轮子。
我需要:
创建一个函数,按照 URL 编码列表如何在 shell 中解码 URL 编码的字符串?
function urldecode() { local i="${*//+/ }"; echo -e "${i//%/\\x}"; }
然后按照使用八进制转储在命令行上将字符串转换为十六进制,因此在内存中创建了具有正确值的映射存储桶如果詳細說明測試。
这开始让人感觉像是火箭科学,我无法相信以前没有其他人解决过这个问题,我似乎找不到解决方案。