如何从NGiNX fastcgi_script_name中删除路径段


How to remove a path segment from NGiNX fastcgi_script_name?

这个问题也可能是:"如何用RegEx修改NGiNX变量?",或者:"RegEx反向引用是否有间隙?"

这两个都能解决我的问题。也许有一个非常简单的解决方案,在浏览了几个小时之后,是时候寻求帮助了。

这是一个场景:

请求URI中有一部分将始终存在(对于一种噱头域名+URI组合:-)。我强制存在始终存在的URI路径组件,该组件紧跟在域名之后,如下所示:

http://somedomain.com/basepart/rest/of/the/path?q=123

在上面的示例中,"/basepart"表示始终存在的URI组件。

到目前为止还不错。当我希望基本文件路径为/var/www/somedomain.com/htdocs/而不包含basepart,并且使用php5_fpm代理时,就会出现问题。我显然设置了:

    location /basepart {
            alias /var/www/somedomain.com/htdocs;
            try_files $uri $uri/ /index.php?$args;
    }

但是由于动态文件是在PHP中的,所以我需要使用fastcgi_split_path_info$request_uri来构建SCRIPT_FILENAME/将其传递给php5_fpm。我该怎么做?如何从$fastcgi_script_name$request_uri中删除/basepart,否则PHP将在/var/www/somedomain.com/htdocs/basepart中查找该文件?

我已经考虑过命名的backreferences,或者"收集"或"碎片化"的backreference(我认为regex中不存在这些),这样当fastcgi_split_path_info赋值发生时,我就可以在$fastcgi_script_name中的basepart之前和之后捕获段,但还没有使它们起作用Dayo早些时候在SO:»Nginx是一个Web服务器,而不是一个脚本应用程序。»,并建议使用Lua进行更复杂的脚本编写。但我有一种感觉,我可能忽略了一些非常简单、值得一试的解决方案:-]。

有什么想法吗?

如果其他人偶然发现了这个问题,经过头脑风暴,我想出了一个愚蠢而明显的解决方案:

    root /app/frontend/web/;
    location /api/ {
        alias /app/backend/web/;
        index index.php index.html;
        # Double /api/ because "that's how nginx alias and try_files works together"
        try_files $uri /api//api/index.php$is_args$args;
        location ~ ^/api(/.*'.php(?:'?.*)?)$ {
            try_files $uri /api//api/index.php$is_args$args;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$1;
            ...
        }
    }

即使用正则表达式捕获组。

根据此规则,请求将按以下方式路由:

  /index.html -> /app/frontend/web/index.html
  /test/test.php -> /app/frontend/web/test/test.php as plaintext
  /api/<somepath> -> /app/backend/web/<somepath> (proxied to FPM if .php) if it exists, otherwise /app/backend/web/index.php

alias指令适用于静态网站,但在涉及PHP时就不那么有用了。我的首选解决方案是在不使用/basepart的情况下内部重写URI,然后使用root而不是alias

问题是,许多PHP脚本使用$request_uri来处理请求,而/basepart则被冻结。但是,我们可以指定为REQUEST_URI选择的任何值,并从$uri或捕获中构造更合适的值。在下面的例子中,我在第一次重写后保留了$uri的值,这样它就可以用来将我们修改后的请求URI传递给PHP脚本。

root /var/www/somedomain.com/htdocs;
location ^~ /basepart {
    rewrite ^/basepart/(.*)$ /$1 last;
    rewrite ^ / last;
}
location / {
    internal;
    try_files $uri @index;
}
location @index {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/index.php;
    fastcgi_param REQUEST_URI $uri;
    ...
}
location ~ '.php$ {
    internal;
    try_files $uri @index;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param REQUEST_URI $uri;
    ...
}

fastcgi代码块在两个位置上重复。如果它变得难以处理,则可以将通用代码放入一个单独的包含文件中。

通过使用internal指令使位置成为私有位置,使/basepart对于外部访问是强制性的。