NginX:捕获根目录之外的所有文件,但有例外

NginX: catch all file outside of root dir, with exceptions

我正在构建一个站点 运行ning NginX / PHP 并希望所有访问都由 /private/routes.php 处理。 但我也想为 css/js-files 和 public 目录(和子目录)中的奇数 php 文件添加一些例外。

文件夹/文件结构:

/var/www/domain.com
                   /private/routes.php
                   /public/test.php
                   /public/css/main.css
                   /public/js/main.js

我当前的 NginX 配置:

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

  server_name domain.com;
  root /var/www/domain.com/public;

  #index index.php;

  #allow existing css files
  location /css/ {
     try_files $uri =404;
  }

  #allow my defined php files
  location /test.php {
     try_files $uri =404;
  }

  #route everything else to my catch-all file
  location / {
    root /var/www/domain.com;
    try_files /private/nada.php /private/routes.php;

    #must add php here because of redefined root
    location ~ \.php$ {
      include snippets/fastcgi-php.conf;
      fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
  }

  #handle allowed php files
  location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
  }

}

以上配置有效但存在一些问题:

  1. 我需要将 root 重新定义为 运行 捕获所有文件 (/private/routes.php).
  2. 因为 #1 我需要在位置中添加 .php ,所以我最终得到 2 php-location-configs.
  3. 出于某种原因,如果我从“try_files”.
  4. 中删除“/private/nada.php”,它就不起作用了
  5. None-存在.php-文件在/public returns 404 而不是被包罗万象。

我可以将根设置为“/var/www/domain”,但这似乎没有必要,因为只有万能的才会使用其他东西。

有什么好的方法可以稍微清理一下吗?

你的配置真是一团糟。我不会解释每一个错误,否则会使答案长 10 倍。我花了一些时间才弄清楚它是如何部分可行的。这里最有趣的是你的 location /test.php { ... } 并不是真的用来处理 /test.php 请求(或者你得到了 test.php 源代码作为响应),但是如果你删除它,该请求将由嵌套的 PHP 处理程序而不是根处理程序处理。

由于您要实现的配置不属于通常的用例,因此您不应使用 fastcgi-php.conf 它是某种 pre-written PHP-FPM 处理程序,可用于大多数情况情况。它不是 nginx 团队提供的默认 nginx 包的一部分,但一些发行版与 nginx 一起打包,尤其是 Debian-based 发行版。因为它已经包含 try_files 指令,而我们需要使用自定义 try_files 代替,我们不能使用该文件,否则 nginx 会抱怨重复使用 try_files

这是一个应该有效的配置:

server {
    ...
    root /var/www/domain.com/public;

    # process an existing non-PHP file as a static one, fallback otherwise
    location / {
        try_files $uri @fallback;
    }

    # process an existing PHP file through PHP-FPM, fallback otherwise
    location ~ \.php$ {
        try_files $uri @fallback;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$uri;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }

    # fallback to /private/routes.php
    location @fallback {
        include fastcgi_params;
        # we don't need a "root" directive here
        # instead we can specify the fallback filename directly
        fastcgi_param SCRIPT_FILENAME /var/www/domain.com/private/routes.php;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
}

这种PHP-FPM用法与通常的用法略有不同,因为在fastcgi_params文件中定义了几个FastCGI变量,这些变量取决于nginx或实际使用的root $uri变量值:

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;

我从未见过任何 PHP 脚本以某种方式依赖这些,通常的做法是依赖 REQUEST_URI 变量值,但我认为值得注意这种差异。但是,如果需要,可以重新定义这些变量(在这种情况下,应该在 include fastcgi_params; 行之后完成)。例如,以下将完全模拟 PHP 处理程序的通常行为:

    location @fallback {
        include fastcgi_params;
        fastcgi_param SCRIPT_NAME /private/routes.php;
        fastcgi_param DOCUMENT_URI /private/routes.php;
        fastcgi_param DOCUMENT_ROOT /var/www/domain.com;
        fastcgi_param SCRIPT_FILENAME /var/www/domain.com/private/routes.php;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }

或者您可以定义一个不同的根,重写一个 URI 并使用常用的:

    location @fallback {
        root /var/www/domain.com;
        rewrite ^ /private/routes.php break;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$uri;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }

但是,如前所述,很可能不需要。

如果在 public 目录下您有包含 index.php 文件的子目录,并且您希望这些文件可用而不用文件名指定完整路径(例如 domain.com/subdir/ 而不是 domain.com/subdir/index.php), 将根位置更改为这个:

    location / {
        index index.php;
        try_files $uri $uri/ @fallback;
    }