为什么 try_files 中的 `/` 会中断 `~ \.php$`

Why does `/` in try_files break `~ \.php$`

我想弄清楚为什么前置 / 不允许 \.php$ locations 指令获取脚本。

下面是我用于 nginx 的示例 .conf。我们是 运行 API 代码,在路径中版本化://domian.com/v#.#/endpoint/uri

我们的document_root是版本号下一级目录; index.php 存在于版本目录中:path/to/sites/public/v1.0/index.php

index index.php # <-- this is in here globally
location ~ ^/(?<version>v[\d\.]+) {
    try_files $uri $version/index.php?$args;
    # Why does this NOT work? The / stopping \.php$ from matching
    # try_files $uri /$version/index.php?$args;
}

location ~ \.php$ {

    fastcgi_pass php56;
    fastcgi_index index.php;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;
    [...]
}

我已经尝试了各种方法,但似乎无法正常工作。一旦我删除 / 它按预期工作,但随后我的 SCRIPT_FILENAME 行从:

    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

收件人:

    fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;

这会中断直接 PHP 文件调用——这是我不想要的。

编辑:解决方案:回答如下:问题与匹配顺序有关。模式匹配是最先发现的,而不是最后发现的。

调换顺序成功了。它在第一个 try_files 中失败,因为该模式明确地寻找以 /.

开头的模式

我正在阅读:http://nginx.org/en/docs/http/request_processing.html

A request “/index.php” is also matched by the prefix location “/” first and then by the regular expression “.(php)$”. Therefore, it is handled by the latter location and the request is passed to a FastCGI server listening on localhost:9000.

首先要注意的是,正则表达式位置是按文件顺序计算的,因此如果 /v1.1 匹配第一个位置块,那么 /v1.1/index.php 也将匹配第一个位置块。您似乎通过创建缺少前导 /.

的错误 URI 来以错误的方式解决问题

详情见this document

您需要将 location ~ \.php$ 块放在 之前 您的 location ~ ^/(?<version>v[\d\.]+) 块以允许 .php 具有版本前缀的文件由 PHP 块处理。