mod_rewrite 到 nginx 重写规则

Posted

技术标签:

【中文标题】mod_rewrite 到 nginx 重写规则【英文标题】:mod_rewrite to nginx rewrite rules 【发布时间】:2012-07-28 17:54:01 【问题描述】:

我已将大部分 Apache HTTPd mod_rewrite 规则转换为 nginx 的 HttpRewrite 模块(在每个动态请求上通过 FastCGI 调用 php-FPM)。由硬位置定义的简单规则可以正常工作:

location = /favicon.ico  rewrite ^(.*)$ /_core/frontend.php?type=ico&file=include__favicon last; 

我仍然遇到正则表达式的问题,它在 mod_rewrite 中像这样解析(请注意,我接受规则中的斜杠,以及将查询字符串附加到每个请求):

mod_rewrite

# File handler
RewriteRule ^([a-z0-9-_,+=]+)\.([a-z]+)$ _core/frontend.php?type=$2&file=$1 [QSA,L]

# Page handler
RewriteRule ^([a-z0-9-_,+=]+)$   _core/frontend.php?route=$1 [QSA,L]
RewriteRule ^([a-z0-9-_,+=]+)\/$ _core/frontend.php?route=$1 [QSA,L]

RewriteRule ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)$   _core/frontend.php?route=$1/$2 [QSA,L]
RewriteRule ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/$ _core/frontend.php?route=$1/$2 [QSA,L]

RewriteRule ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)$   _core/frontend.php?route=$1/$2/$3 [QSA,L]
RewriteRule ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/$ _core/frontend.php?route=$1/$2/$3 [QSA,L]

我已经为该站点提出了以下服务器配置,但在解析请求后遇到了不匹配的规则(例如:GET /user/auth):

尝试 nginx 重写

location / 
    # File handler
    rewrite ^([a-z0-9-_,+=]+)\.([a-z]+)?(.*)$                                /_core/frontend.php?type=$2&file=$1&$3 break;

    # Page handler
    rewrite ^([a-z0-9-_,+=]+)(\/*)?(.*)$                                     /_core/frontend.php?route=$1&$2        break;
    rewrite ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)(\/*)?(.*)$                   /_core/frontend.php?route=$1/$2&$3     break;
    rewrite ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)(\/*)?(.*)$ /_core/frontend.php?route=$1/$2/$3&$4  break;

对于处理我的文件处理程序(只是 filename.ext)和我的页面处理程序(这是一个由正斜杠定义的最多 3 个属性的唯一路由请求),您有什么建议?强>

由于我还没有得到回复,我也不确定这是否会覆盖我用location ~ \.php 定义的 PHP 解析器,它包含在这些重写规则之前。

如果我能够解决解析问题而无需为每个路由属性数量使用新规则,则可以获得奖励积分。

【问题讨论】:

【参考方案1】:

我最终写了以下规则:

文件处理程序

location ~ ^/([a-zA-Z0-9-_]*)\.([a-zA-Z0-9]*)$  include /web/_config/php.conf; rewrite ^/([a-zA-Z0-9-_]*)\.([a-zA-Z0-9]*)$ /_core/frontend.php?type=$2&file=$1 last; 

文件处理程序获取名称和扩展名并将其写入 type=ext&file=name。

页面处理程序

location ~ ^/([a-z0-9-_]*)$  include /web/_config/php.conf; rewrite ^/([a-z0-9-_]*)$ /_core/frontend.php?route=$1 last; 
location ~ ^/([a-z0-9-_]*)/?([a-z0-9-_]*)$  include /web/_config/php.conf; rewrite ^/([a-z0-9-_]*)/?([a-z0-9-_]*)$ /_core/frontend.php?route=$1/$2 last; 
location ~ ^/([a-z0-9-_]*)/?([a-z0-9-_]*)/?([a-z0-9-_]*)$  include /web/_config/php.conf; rewrite ^/([a-z0-9-_]*)/?([a-z0-9-_]*)/?([a-z0-9-_]*)$ /_core/frontend.php?route=$1/$2/$3 last; 

页面处理程序(在这种情况下最多处理 3 个“目录”)抓取每个分隔符 (/) 之间的字符串,执行正则表达式验证并将其写入查询字符串。

这与我的原始配置的主要区别在于每个条目都有自己的位置处理程序,使用last 规则它会在第一次匹配时处理它,因此性能应该会稍微好一些。

我还发现 nginx 默认会附加查询字符串,因此不需要正则表达式,这是另一个性能改进。

请注意,/web/_config/php.conf 只是一个 FastCGI 直通配置,nginx 附带的配置(通常是/etc/nginx/fastcgi.conf)应该可以正常工作。请注意,如果您专门处理 PHP,则不需要在每个规则中定义它,只需在它们前面加上 include。

希望这会有所帮助。

【讨论】:

以上是关于mod_rewrite 到 nginx 重写规则的主要内容,如果未能解决你的问题,请参考以下文章

使用 mod_rewrite 重写用户代理规则

apache mod_rewrite - 重写规则

Apache的Mod_rewrite学习(RewriteRule重写规则的语法) 转

apache mod_rewrite:如何根据其他目录中的文件存在为同一目录添加不同的重写规则?

在 mod_rewrite 规则正则表达式中匹配问号

复杂的 htaccess 重写规则 - 我从哪里开始?