我们刚刚从 Apache 2 迁移到 nginx,并且遇到了一些重写规则问题。以下是在 Apache 上可以正常工作的:
RewriteEngine on
Options +FollowSymLinks
#RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
#RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/p([0-9]+)-(.*)-page([0-9+]).html$ showproduct.php?product=$2&cpage=$4 [L]
RewriteRule ^(.*)/p([0-9]+)-(.*).html$ showproduct.php?product=$2 [L]
RewriteRule ^(.*)/p([0-9]+).html$ showproduct.php?product=$2 [L]
RewriteRule ^g([0-9]+)-(.*)-page([0-9]+).html$ showcat.php?cat=$1&page=$3 [L]
RewriteRule ^g([0-9]+)-(.*).html$ showcat.php?cat=$1 [L]
RewriteRule ^(.*)/index([0-9]+)-([0-9]+).html$ index.php?cat=$2&page=$3 [L]
RewriteRule ^(.*)/index([0-9]+).html$ index.php?cat=$2 [L]
RewriteRule ^m([0-9]+)-(.*)-protype([0-9]+).html$ member.php?uid=$1&protype=$3 [L]
RewriteRule ^m([0-9]+)-(.*).html$ member.php?uid=$1 [L]
RewriteRule ^board.html$ board.php [L]
RewriteRule ^b([0-9]+)-(.*).html$ board.php?msg=$1 [L]
RewriteRule ^u([0-9]+)-(.*)-page([0-9]+).html$ showcat.php?ppuser=$1&page=$3 [L]
RewriteRule ^u([0-9]+)-(.*).html$ showcat.php?ppuser=$1 [L]
RewriteRule ^s([0-9]+)-(.*)-page([0-9]+).html$ showmembers.php?cat=$1&page=$3 [L]
RewriteRule ^s([0-9]+)-(.*).html$ showmembers.php?cat=$1 [L]
我们把它变成了这样:
location /classifieds/ {
rewrite ^/classifieds/(.*)/p([0-9]+)-(.*)-page([0-9+]).html$ /classifieds/showproduct.php?product=$2&cpage=$4 permanent;
rewrite ^/classifieds/(.*)/p([0-9]+)-(.*).html$ /classifieds/showproduct.php?product=$2 permanent;
rewrite ^/classifieds/(.*)/p([0-9]+).html$ /classifieds/showproduct.php?product=$2 permanent;
rewrite ^/classifieds/g([0-9]+)-(.*)-page([0-9]+).html$ /classifieds/showcat.php?cat=$1&page=$3 permanent;
rewrite ^/classifieds/g([0-9]+)-(.*).html$ /classifieds/showcat.php?cat=$1 permanent;
rewrite ^/classifieds/(.*)/index([0-9]+)-([0-9]+).html$ /classifieds/index.php?cat=$2&page=$3 permanent;
rewrite ^/classifieds/(.*)/index([0-9]+).html$ /classifieds/index.php?cat=$2 permanent;
rewrite ^/classifieds/m([0-9]+)-(.*)-protype([0-9]+).html$ /classifieds/member.php?uid=$1&protype=$3 permanent;
rewrite ^/classifieds/m([0-9]+)-(.*).html$ /classifieds/member.php?uid=$1 permanent;
rewrite ^/classifieds/board.html$ /classifieds/board.php permanent;
rewrite ^/classifieds/b([0-9]+)-(.*).html$ /classifieds/board.php?msg=$1 permanent;
rewrite ^/classifieds/u([0-9]+)-(.*)-page([0-9]+).html$ /classifieds/showcat.php?ppuser=$1&page=$3 permanent;
rewrite ^/classifieds/u([0-9]+)-(.*).html$ /classifieds/showcat.php?ppuser=$1 permanent;
rewrite ^/classifieds/s([0-9]+)-(.*)-page([0-9]+).html$ /classifieds/showmembers.php?cat=$1&page=$3 permanent;
rewrite ^/classifieds/s([0-9]+)-(.*).html$ /classifieds/showmembers.php?cat=$1 permanent;
}
这不起作用。当我们尝试访问我们的 URL 时,我们得到的只是 nginx 404。我们对 nginx 还很陌生(这些规则适用于我们无法修改的第三方软件),因此任何指示都将不胜感激。
**更新:** 以下是一些(希望)有用的信息。请求 URL 时,日志表明在重写发生之前发生了 404:
2013/03/11 10:38:18 [error] 10073#0: *13003643 open() "/home/site/public_html/classifieds/category-name-here/p1097-product.html" failed (2: No such file or directory), client: IP, server: site.com, request: "GET /classifieds/category-name-here/p1097-product.html HTTP/1.1", host: "www.site.com"
完整配置文件如下:
server {
server_name site.com www.site.com;
root "/home/site/public_html";
index index.php;
client_max_body_size 10m;
access_log /home/site/_logs/access.log;
error_log /home/site/_logs/error.log;
location /classifieds/ {
rewrite ^/classifieds/(.*)/p([0-9]+)-(.*)-page([0-9+]).html$ /classifieds/showproduct.php?product=$2&cpage=$4 permanent;
rewrite ^/classifieds/(.*)/p([0-9]+)-(.*).html$ /classifieds/showproduct.php?product=$2 permanent;
rewrite ^/classifieds/(.*)/p([0-9]+).html$ /classifieds/showproduct.php?product=$2 permanent;
rewrite ^/classifieds/g([0-9]+)-(.*)-page([0-9]+).html$ /classifieds/showcat.php?cat=$1&page=$3 permanent;
rewrite ^/classifieds/g([0-9]+)-(.*).html$ /classifieds/showcat.php?cat=$1 permanent;
rewrite ^/classifieds/(.*)/index([0-9]+)-([0-9]+).html$ /classifieds/index.php?cat=$2&page=$3 permanent;
rewrite ^/classifieds/(.*)/index([0-9]+).html$ /classifieds/index.php?cat=$2 permanent;
rewrite ^/classifieds/m([0-9]+)-(.*)-protype([0-9]+).html$ /classifieds/member.php?uid=$1&protype=$3 permanent;
rewrite ^/classifieds/m([0-9]+)-(.*).html$ /classifieds/member.php?uid=$1 permanent;
rewrite ^/classifieds/board.html$ /classifieds/board.php permanent;
rewrite ^/classifieds/b([0-9]+)-(.*).html$ /classifieds/board.php?msg=$1 permanent;
rewrite ^/classifieds/u([0-9]+)-(.*)-page([0-9]+).html$ /classifieds/showcat.php?ppuser=$1&page=$3 permanent;
rewrite ^/classifieds/u([0-9]+)-(.*).html$ /classifieds/showcat.php?ppuser=$1 permanent;
rewrite ^/classifieds/s([0-9]+)-(.*)-page([0-9]+).html$ /classifieds/showmembers.php?cat=$1&page=$3 permanent;
rewrite ^/classifieds/s([0-9]+)-(.*).html$ /classifieds/showmembers.php?cat=$1 permanent;
}
location / {
try_files $uri $uri/ /index.php$uri?$args;
}
location ~ "^(.+\.php)($|/)" {
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SERVER_NAME $host;
if ($uri !~ "^/uploads/") {
fastcgi_pass 127.0.0.1:9006;
}
include fastcgi_params;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
access_log off;
}
location ~* \.(html|htm)$ {
expires 30m;
}
location ~* /\.(ht|git|svn) {
deny all;
}
}
**更新 2:** 将我的位置行更改为 location ^~ /classifieds/ 后,我们终于能够使重写正常工作,但却遇到了重定向循环。例如,URL /classifieds/g2-general-category.html 被正确地重写为 /classifieds/showcat.php?cat=2,但似乎脚本检测到了此重写并尝试将用户发送到正确的 SEO URL,该 URL 重写为 showcat.php,如此循环往复。此外,重写循环完成后,我的浏览器 URL 栏会在 50% 的时间内显示 showcat.php,在另外 50% 的时间内显示 g2-general-category.html。所以我想我的问题是 - 我们如何避免这种行为?在我外行看来,发生的事情似乎是:
用户访问 g2-general-category.html。nginx 将用户发送到 showcat.php?cat=2 PHP 脚本发现用户没有使用 SEO 的 URL,因此执行标头重定向以将其发送到正确的 URL,然后 nginx 再次将其重写为 showcat.php?cat=2。
答案1
这些rewrite
指令看起来是正确的。
但是,根据您提供的信息,我无法告诉您哪里出了问题。
查出在哪里发生以下事情
404
:前或者后重定向。
检查日志文件或使用浏览器内置的开发工具(如萤火虫)来遵循重定向流程。给定的代码片段就是你在
server
块内得到的全部内容吗?处理重定向目标的逻辑又是什么呢?
你还应该发布其余部分。另外,请留意
location
可能干扰 URL 的其他块。
请参阅nginx 文档用于匹配 s 的顺序location
。
更新: 我想我发现了你的错误:
该location ~* \.(html|htm)$
块通常会匹配您所有的请求,/classifieds/
因为数学引擎默认首选正则表达式。
要提高优先级,location /classifieds/
您应该使用以下^~
标志:
location ^~ /classifieds/ {
# REWRITES HERE
}
相应的文档入口:
可以使用“^~”前缀在文字字符串匹配后禁用正则表达式检查。如果最具体的匹配文字位置有此前缀:则不检查正则表达式。
重定向循环:
看起来您想保留 SEO 友好的 URI 以保持外观。
在这种情况下,请修改rewrite
s 以仅在内部重写 - 而不重定向浏览器。
为了实现此行为,请使用标志last
代替,permanent
如下所示:
rewrite SEO-PATTERN INTERNAL-URI last;
然后位置匹配引擎将尝试匹配重写 URI.
和触发 HTTP 重定向(临时/永久),redirect
并且permanent
last
break
只会影响内部URI价值。
这一切都描述在文档。