【问题标题】:Nginx serving static files with 404 status code?Nginx 使用 404 状态码提供静态文件?
【发布时间】:2016-10-03 22:05:00
【问题描述】:

我正在尝试让 Nginx 使用 PHP 为经过身份验证的管理员用户提供一些静态文件。这很好用,我取回了文件。但它有一个 404 状态码..

我正在使用以下 (Symfony / Silex) php 代码:

use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

$filePath = '/usr/share/nginx/project/src/path/to/my/protected/static/dir/' . $file;
if (empty($file) || !is_readable($filePath)) {
    $app->abort(404);
}

$response = new BinaryFileResponse($filePath);
$response->trustXSendfileTypeHeader();
$response->setPrivate();
$response->setContentDisposition(
    ResponseHeaderBag::DISPOSITION_INLINE,
    $file,
    iconv('UTF-8', 'ASCII//TRANSLIT', $file)
);
$response->headers->addCacheControlDirective('must-revalidate', true);
return $response;

这是我的 nginx 配置:

server {
    listen          443;
    listen          [::]:443;

    root            /usr/share/nginx/project/web;
    index           index.php;
    error_page      401 403 404 /404.html;

    server_name     example.com;

    rewrite ^/(.*)/$ /$1 permanent;

    location / {
        # First attempt to serve request as file, then
        # as directory, then let php handle the file
        try_files $uri $uri/ /index.php$is_args$args;
        index index.php;
        autoindex off;

        location ~*  \.(svg|jpg|jpeg|png|gif|ico|css|js)$ {
            expires 150d;
        }
    }

    location ~ \.php$ {
        set $path_info $fastcgi_path_info;
        fastcgi_index index.php;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;

        try_files $uri $uri/ /index.php$is_args$args;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;

        include fastcgi_params;
        fastcgi_param APP_ENV production;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

受保护的目录位于 nginx 配置中的根目录之外 (/usr/share/nginx/project/web)。

我在日志中发现了这些错误消息:

open() "/usr/share/nginx/project/web/admin/static/admin.js" failed 
(2: No such file or directory), 
request: "GET /admin/static/admin.js HTTP/1.1"

/admin/static/admin.js 确实是请求的 url。

更新 1

看起来 nginx 总是尝试打开 url 并在错误日志中添加一个条目,即使 php 处理响应也很好。

即使我将所有 php 代码替换为:return new Response('test', 200);,body 'test' 的响应代码仍然是 404...

我还尝试在我的 nginx 配置中添加一个额外的位置块:

location /protected_admin_files {
    internal;
    alias /usr/share/nginx/project/src/path/to/my/protected/static/dir;
}

然后尝试像这样重定向到文件:

return new Response('', 200, [
    'X-Accel-Redirect' => '/protected_admin_files/' . $file
]);

但也没有运气。与正确的响应正文相同的 404...

【问题讨论】:

  • 如果您有终端访问权限,请在您的静态文件夹中执行$ pwd
  • 然后,我将该位置与$filePath = __DIR__ . '/src/path/to/my/protected/static/dir/';的输出进行比较
  • 请记住,PHP 可能会以 Web 服务器运行的用户 ID 访问文件(通常是“nobody”)。 PHP 5.1.5 之前不考虑安全模式限制。
  • 我这样做了,两者都是一样的。运行 PHP 7.0 顺便说一句。
  • 发现问题..查看答案。

标签: php symfony nginx silex x-accel-redirect


【解决方案1】:

我自己找到了原因..

这是我将错误级别设置为debug (here's the full log) 后在错误日志中发现的内容

...
[debug] rewrite phase: 1
[debug] http script regex: "^/(.*)/$"
[notice] "^/(.*)/$" does not match "/admin/static/admin.js", request: "GET /admin/static/admin.js HTTP/1.1", host: "example.com"
[debug] test location: "/"
[debug] test location: "protected_admin_files"
[debug] test location: ~ "\.(svg|jpg|jpeg|png|gif|ico|css|js)$"
[debug] using configuration "\.(svg|jpg|jpeg|png|gif|ico|css|js)$"
...
[debug] http filename: "/usr/share/nginx/project/web/admin/static/admin.js"
[debug] add cleanup: 00000000025AE108
[error] open() "/usr/share/nginx/project/web/admin/static/admin.js" failed (2: No such file or directory), client: 24.132.134.203, server: example.com, request: "GET /admin/static/admin.js HTTP/1.1", host: "example.com"
[debug] http finalize request: 404, "/admin/static/admin.js?" a:1, c:1
[debug] http special response: 404, "/admin/static/admin.js?"
[debug] internal redirect: "/index.php?"
...

显然,我的第一个 location / 块中的嵌套 location 导致了 404。

location / {
    try_files $uri $uri/ /index.php$is_args$args;
    index index.php;
    autoindex off;

    location ~*  \.(svg|jpg|jpeg|png|gif|ico|css|js)$ {
        expires 150d;
    }
}

由于扩展名而匹配,使 Nginx 去寻找文件。由于没有找到它,因此 404 已设置并且显然不会在稍后的过程中被覆盖,当 php 返回 X-Accel-Redirect 标头时:(。

【讨论】:

    猜你喜欢
    • 2015-11-30
    • 2018-10-12
    • 2017-09-04
    • 2018-10-23
    • 1970-01-01
    • 2013-06-27
    • 2014-01-12
    • 2021-05-27
    • 1970-01-01
    相关资源
    最近更新 更多