使用 try_files 并在 NGINX 位置块中重写,使用默认的前端控制器文件

Using try_files and rewrite within an NGINX location block, with a default front-controller file

我正在从旧框架迁移到 php 中的新框架。旧框架每个 URL 都有一个登陆页面,例如:

  1. test.com/page1 将被路由到 public_directory/page1.php

  2. test.com/another_page 将被路由到 public_directory/another_page.php

以下块用于这些请求:

location / { 
    limit_req zone=globallimit burst=20 nodelay;
    try_files $uri $uri/ @php; 
}

location @php {         
    rewrite ^(/[^/]+)$ .php last;
    rewrite ^(/[^/]+)/(.*)$ .php?q= last;
}

新框架使用前端控制器,每个请求都需要指向public_directory/front_controller.php。在我们迁移时,我们将删除旧的登陆文件,这是我们识别哪些页面使用新框架的方式。

我认为可行的是以下,在 @php 块之后,将默认参数添加到 front_controller.php:

location / { 
    limit_req zone=globallimit burst=20 nodelay;
    try_files $uri $uri/ @php /front_controller.php?$arg; 
}

location @php {         
    rewrite ^(/[^/]+)$ .php last;
    rewrite ^(/[^/]+)/(.*)$ .php?q= last;
}

如果@php重写块不匹配一个文件,那么它应该默认为/front_controller.php?arg;但是,我发现现在 @php 被忽略了,nginx 直接转到 front_controller.php。我哪里出错了,为什么 @php 重写现在被忽略了?

try_files 指令需要一个文件列表,后跟 URI/命名位置/HTTP 错误代码,如果列表中的 none 个文件存在,将使用这些文件。假设您的站点根目录是 /home/user/www 并且您的请求是 http://example.com/some/path 此配置检查是否存在以下 files/directories:

  1. /home/user/www/some/path 文件,如果找到该文件,其内容将在响应正文中返回。
  2. /home/user/www/some/path/ 目录,如果这个目录存在,它会检查所有可能用 index 指令定义的索引文件,第一个找到的文件将被使用。如果在此目录中找不到索引文件,nginx returns 目录内容如果有 autoindex on; 或 HTTP 403 Forbidden 否则。
  3. /home/user/www@php 文件。很明显,这个文件是找不到的。

如果 none 这些检查成功,nginx 将遵循定义为最后一个参数的 URI(或命名位置)(在本例中为 /front_controller.php?$arg)。

你可以做的是尝试类似

location ~ ^(/[^/]+)$ {
    try_files .php /front_controller.php?$arg;
}
location ~ ^(?<script>/[^/]+)/(?<param>.*)$ {
    rewrite ^ $script?q=$param last;
}

但是我不明白 $arg 变量应该来自哪里。也许你的意思是 $is_args$args?

更新

我错了,您可以使用 try_files 指令检查 php 脚本是否存在,但该脚本不会传递到您的 php 处理程序位置块。你的任务引起了我的兴趣,最后我得到了一些工作:

# backup original args
set $original_args $args;
if ($uri ~ "^(/[^/]+)(?:/(.*))?$") {
    set $script .php;
    set $param ;
}
if ($param) {
    set $args "q=$param";
}
location / { 
    limit_req zone=globallimit burst=20 nodelay;
    try_files $uri $uri/ @php; 
}
location @php {
    if ( !-f $document_root$script ) {
        # old landing php file is absent, restore original args and rewrite URI to /front_controller.php
        set $args $original_args;
        set $script /front_controller.php;
    }
    rewrite ^ $script last;
}