具有路由重写的 Nginx 嵌套位置

Nginx nested location with route rewrite

我想在一个站点内嵌套几个专用路由到特定目录,这些目录可能具有不同的名称。我不知道如何重写它用于 try_files.

的路径
server {           
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/default;

    index index.html;

    server_name _;

    if ($bad_referer) {
        return 444;
    }

    location / {
        try_files $uri $uri/ =404;
    }

    location /postfixadmin/ {
        access_log /var/log/nginx/postfixadmin/access.log;
        error_log /var/log/nginx/postfixadmin/error.log;

        root /var/www/postfixadmin/;
        index index.php index.html index.htm;
        try_files $uri $uri/ /index.php;


        location ~ \.php$ {
            include fastcgi.conf;
            fastcgi_index index.php;
            fastcgi_intercept_errors on;
            fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        }

        location ~* \.(css|js|gif|jpe?g|png|woff|woff2|ttf|eot|svg|ico)$ {
            expires 168h;
            add_header Pragma public;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
        }
    }

    location /email/ {

        #access_log /var/log/nginx/roundcube/access.log;
        #error_log /var/log/nginx/roundcube/error.log;

        root /var/www/roundcube/;
        index index.php index.html index.htm;
        try_files $uri $uri/ /index.php;

        location ~ \.php$ {
            include fastcgi.conf;
            fastcgi_index index.php;
            fastcgi_intercept_errors on;
            fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        }

        location ~* \.(css|js|gif|jpe?g|png|woff|woff2|ttf|eot|svg|ico)$ {
            expires 168h;
            add_header Pragma public;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
        }
    }
}

当我导航到 www.site.com/email 时,我收到 404,我假设这是因为它正在寻找 /var/www/roundcube/email/index.php,但它不存在。 try_files之前的文件路径怎么改写?

我想出了解决办法,事实证明它相当简单。使用 alias 而不是 root 仅使用匹配 location 部分之后的字符串部分,所以我在正确的目录中查找。另一个问题是 PHP 没有传递正确的脚本名称,所以它仍然在错误的地方查找。解决方案是传入 fastcgi_param SCRIPT_FILENAME $request_filename;。我也能够摆脱 try_files 部分,尽管我不是 100% 确定原因。

以下是可行的解决方案:

server {           
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/default;

    index index.html;

    server_name _;

    if ($bad_referer) {
        return 444;
    }

    try_files $uri $uri/ =404;

    location /postfixadmin {
        alias /var/www/postfixadmin/;
        index index.php index.html index.htm;

        location ~ /postfixadmin/.+\.php$ {
            include fastcgi.conf;
            fastcgi_index index.php;
            fastcgi_intercept_errors on;
            fastcgi_param SCRIPT_FILENAME $request_filename;
            fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        }

        location ~* \.(css|js|gif|jpe?g|png|woff|woff2|ttf|eot|svg|ico)$ {
            expires 168h;
            add_header Pragma public;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
        }
    }

    location /email {
        alias /var/www/roundcube/;
        index index.php index.html index.htm;

        location ~ /email/.+\.php$ {
            include fastcgi.conf;
            fastcgi_index index.php;
            fastcgi_intercept_errors on;
            fastcgi_param SCRIPT_FILENAME $request_filename;
            fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        }

        location ~* \.(css|js|gif|jpe?g|png|woff|woff2|ttf|eot|svg|ico)$ {
            expires 168h;
            add_header Pragma public;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
        }
    }
}