带有尾部斜杠的奇怪 Nginx 行为
Strange Nginx behavior with trailing slashes
我有一个非常有趣的行为。我想避免在我的网站上的 URL 中使用尾部斜杠。我已将 rewrite ^/(.*)/$ / permanent;
规则放入我的服务器块,所以
https://example.com/something/
,
https://example.com/something////
重定向到
https://example.com/something
;
和
https://example.com/
重定向到
https://example.com
但是https://example.com////
被重定向到... https://enjoygifts.ru////
(实际上不要重定向,它是200代码)。为什么?
这是我的服务器块:
server {
listen 443 ssl;
...
... ssl directives
...
root /var/www/mysite.com;
index index.php;
server_name mysite.com;
rewrite ^/(.*)/$ / permanent;
location / {
rewrite ^/.*$ /index.php last;
}
location ~ ^/index.php {
try_files $uri =404;
include /etc/nginx/fastcgi.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
location ~ ^/storage/app/uploads/public { try_files $uri 404; }
...
... lot of similar location blocks
...
}
https://example.com
并不真正存在,根 URI 是 /
- 它在浏览器地址栏中的显示方式取决于浏览器 - 有些会自动显示单独的 /
而其他人会删除一个孤零零的 /
.
所以你不能从 https://example.com/
重定向到 https://example.com
- 它会被默默地解释为从 https://example.com/
到 https://example.com/
的重定向。
Nginx 在评估 location
和 rewrite
语句时使用 normalized URI,并生成 $uri
变量。多个连续出现的 /
折叠成单个 /
.
虽然正则表达式 ^/(.*)/$
与 URI //
匹配,但语句永远不会看到它。因为 Nginx 已经将该 URI 规范化为 /
,这与正则表达式不匹配。
如果具有多个 /
的根 URI 有问题,请将正则表达式应用于 $request_uri
变量,该变量包含规范化之前的原始 URI,还包括查询字符串(如果有的话) ).
例如:
if ($request_uri ~ "^/{2,}(\?|$)") {
return 301 /$is_args$args;
}
这可以放在您的 location / {...}
块内。请参阅 this caution 关于 if
.
的用法
我有一个非常有趣的行为。我想避免在我的网站上的 URL 中使用尾部斜杠。我已将 rewrite ^/(.*)/$ / permanent;
规则放入我的服务器块,所以
https://example.com/something/
,
https://example.com/something////
重定向到
https://example.com/something
;
和
https://example.com/
重定向到
https://example.com
但是https://example.com////
被重定向到... https://enjoygifts.ru////
(实际上不要重定向,它是200代码)。为什么?
这是我的服务器块:
server { listen 443 ssl; ... ... ssl directives ... root /var/www/mysite.com; index index.php; server_name mysite.com; rewrite ^/(.*)/$ / permanent; location / { rewrite ^/.*$ /index.php last; } location ~ ^/index.php { try_files $uri =404; include /etc/nginx/fastcgi.conf; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; } location ~ ^/storage/app/uploads/public { try_files $uri 404; } ... ... lot of similar location blocks ... }
https://example.com
并不真正存在,根 URI 是 /
- 它在浏览器地址栏中的显示方式取决于浏览器 - 有些会自动显示单独的 /
而其他人会删除一个孤零零的 /
.
所以你不能从 https://example.com/
重定向到 https://example.com
- 它会被默默地解释为从 https://example.com/
到 https://example.com/
的重定向。
Nginx 在评估 location
和 rewrite
语句时使用 normalized URI,并生成 $uri
变量。多个连续出现的 /
折叠成单个 /
.
虽然正则表达式 ^/(.*)/$
与 URI //
匹配,但语句永远不会看到它。因为 Nginx 已经将该 URI 规范化为 /
,这与正则表达式不匹配。
如果具有多个 /
的根 URI 有问题,请将正则表达式应用于 $request_uri
变量,该变量包含规范化之前的原始 URI,还包括查询字符串(如果有的话) ).
例如:
if ($request_uri ~ "^/{2,}(\?|$)") {
return 301 /$is_args$args;
}
这可以放在您的 location / {...}
块内。请参阅 this caution 关于 if
.