无法使简单的 nginx 重写规则在子目录中起作用

无法使简单的 nginx 重写规则在子目录中起作用

我们刚刚从 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 以保持外观。
在这种情况下,请修改rewrites 以仅在内部重写 - 而不重定向浏览器。

为了实现此行为,请使用标志last代替,permanent如下所示:

rewrite SEO-PATTERN INTERNAL-URI last;

然后位置匹配引擎将尝试匹配重写 URI.
和触发 HTTP 重定向(临时/永久),redirect并且permanentlastbreak只会影响内部URI价值。
这一切都描述在文档

相关内容