我为 nginx 转换了一些 mod_rewrite 规则,当我在本地测试时它们运行良好,但由于某种原因,它们无法在我的网站上运行。
有人能帮我指出我错在哪里吗?
Apache 规则:
<filesMatch "\.(htm|html|css|js|php)$">
AddDefaultCharset UTF-8
DefaultLanguage en-US
</filesMatch>
<IfModule mod_rewrite.c>
ErrorDocument 404 /404.php
RewriteEngine On
RewriteRule ^article.*$ / [R=301,L]
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*\.* /loadpage.php [QSA,L]
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*\.html /courses/index.php [L]
</IfModule>
Nginx 转换规则:
charset utf-8;
error_page 404 /404.php;
location /article {
rewrite ^/article.*$ / redirect;
}
location / {
if (!-e $request_filename){
rewrite ^/.*\.* /loadpage.php break;
}
}
if (!-e $request_filename){
rewrite ^/.*\.html /courses/index.php break;
}
答案1
问题
您的最后一条重写规则在任何location
块之外。诚然,我不确定 nginx 如何处理匹配位置块内部和内部都有重写规则的情况server
(我认为它总是使用内部的重写规则,server
因为这是首先评估的)。然而,我可以肯定的是,这会导致意想不到的结果。
解决方案
首先,if 是邪恶的。除非绝对没有其他方法可以达到相同的结果(这实际上只会在非常不明显的情况下发生),否则不要使用它。
检查文件是否存在的更好的方法是try_files指示。
按指定顺序检查文件是否存在,并使用第一个找到的文件进行请求处理;处理在当前上下文中执行。根据 root 和 alias 指令,从文件参数构建文件路径。可以通过在名称末尾指定斜杠来检查目录是否存在,例如“$uri/”。如果没有找到任何文件,则进行内部重定向到最后一个参数指定的 uri。
您的重写规则将如下所示:
charset utf-8;
error_page 404 /404.php;
location /article {
rewrite ^/article.* / redirect;
}
location / {
try_files $uri $uri/ /loadpage.php?$args;
}
最后一条重写规则很可能是有问题的,它try_files
在其自己的位置块中看起来像这样:
location ~ \.html$ {
try_files $uri /courses/index.php?$args;
}
修饰符~
告诉 nginx,此位置使用正则表达式。它匹配所有以 结尾的 URI .html
。此位置块优先于其他位置块,因为它是更具体(正则表达式位置块在“正常”位置块之前进行检查)。有关 nginx 位置块选择的更多信息。
附加说明和资源
由于您匹配,因此$
after是多余的^/article.*
全部无论如何,后面都必须有 125 个字符。附加?$args
到指令的 URItry_files
可确保所有GET
参数都传递给它。