我正在尝试删除网址中的所有尾部斜杠。除了主页之外,这在任何地方都有效。
这就是它的工作原理:
这里不起作用:
我的配置文件:
server {
server_name sub.example.com;
root /var/www/example.com/;
index index.php;
charset utf-8;
rewrite ^/(.*)/$ /$1 permanent;
location / {
try_files $uri /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
listen 443 ssl;
#SSL settings
}
看来您不了解幕后的一些非常重要的部分。
GET
请求不能包含空字符串作为路径。
当您在浏览器地址栏输入
sub.example.com/
时,浏览器会隐藏尾部斜杠。这仅适用于根请求,在任何其他情况下(包括 sub.example.com//
、sub.example.com/test/
、sub.example.com/test//
等),您都会在地址栏看到完整路径。无论你是否输入斜杠,浏览器发出的 HTTP 请求都会是这样的
GET / HTTP/1.1
Host: sub.example.com
...
2。
rewrite
nginx 指令与 标准化 URI 配合使用。
location
和 rewrite
指令都适用于所谓的 标准化 URI:
在解码以“%XX”形式编码的文本后,针对规范化的 URI 执行匹配,解析对相对路径组件“.”的引用。和“..”,并且可能将两个或多个相邻斜杠压缩为单个斜杠。
这意味着,对于所有请求,如
sub.example.com/test/
、sub.example.com/test//
、sub.example.com/test///
等,nginx 将规范化请求 URI 视为 /test/
(这就是您的重写规则在一步而不是四个步骤中工作的原因) -步骤 sub.example.com/test///
-> sub.example.com/test//
-> sub.example.com/test/
-> sub.example.com/test
循环)。
对于任何
sub.example.com/
、sub.example.com//
、sub.example.com///
等请求也是如此,规范化的 URI 将被 nginx 视为 /
,从而使任何重写规则都无法使用。
merge_slashes
指令关闭斜杠压缩(请阅读安全注意事项)。为了防止多次重定向(其中每个重定向仅删除一个尾部斜杠),请为正则表达式模式使用非贪婪 *
和贪婪 +
量词:
merge_slashes off;
rewrite ^(/.*?)/+$ $1 permanent;
看起来好的变体将是下一个配置:
if ($request_uri ~* (.*?)(\/+)$) {
return 301 $scheme://$host$1;
}