Apache 到 Nginx mod_rewrite 规则

Apache 到 Nginx mod_rewrite 规则

我为 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参数都传递给它。

相关内容