如何在 nginx 中设置回退错误页面?

Jim*_*m D 10 nginx

我目前正在配置 nginx 对一些错误页面和其他“默认”媒体文件(例如 favicon.ico 和 robots.txt)的处理,但我遇到了一个小问题,让某些错误页面按照我想要的方式工作.

基本上,我要做的是为该服务器的根目录下的服务器提供某些文件,例如/var/www/someserver.com/robots.txt。如果该文件不存在,我希望 nginx 转到“默认”,即 /var/www/default/robots.txt。这是我如何(成功)配置的基本要点:

server {
    ...
    root /var/www/someserver.com;

    location ~* ^/(robots\.txt)$ {
        error_page 404 = @default;
    }

    location @default {
        root /var/www/default;
    }
}
Run Code Online (Sandbox Code Playgroud)

这很好用。

我正在尝试对错误页面做同样的事情,但我无法做到这一点:

server {
    ...
    root /var/www/someserver.com;

    error_page 404   /404.html;

    location ~* ^/(404\.html)$ {
        error_page 404 = @default;
    }

    location @default {
        root /var/www/default;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您访问 someserver.com/404.html,它会首先尝试加载 /var/www/someserver.com/404.html 然后回退到 /var/www/default /404.html 如果没有找到。但是,如果您访问 someserver.com/blahblah,它只会显示 404 页面(如果它设置在 /var/www/someserver.com/ 中)。如果该文件不存在,它不会回退到默认目录。

无论如何,您可能可以完成我想要完成的任务(这就是我包含第一个工作示例的原因)。

有任何想法吗?

编辑:

根据 Martin F 的回答,这就是我最终整理的内容:

# Doesn't work when error page is returned on a POST request
server {
    ...
    root /var/www/someserver.com;

    error_page  404         = @notfound;
    error_page  500 502 504 = @server_error;
    error_page  503         = @maintenance;

    location @notfound {
        try_files /404.html /../default/404.html =404;
    }

    location @server_error {
        try_files /500.html /../default/500.html =500;
    }

    location @maintenance {
        try_files /503.html /../default/503.html =503;
    }
}
Run Code Online (Sandbox Code Playgroud)

这很棒。上面的 error_pages 和位置的实际块位于每个虚拟主机都包含的 server_defaults.conf 文件中,这就是为什么我没有将路径硬编码到每个位置并使用相对路径作为默认值。

编辑2:

这种方法有问题。如果您 POST 到返回错误的 URL,则 POST 请求方法将与 try_files 尝试一起发送。这(对我而言)会导致 405 Not Allowed 错误,因为 nginx 本质上是在尝试 POST 到 /default/500.html 而不是仅仅获取该页面。

编辑3:

我发布了一个更接近我最初想法的解决方案。

Jim*_*m D 10

我最终选择了更接近我最初想法的东西。我遗漏的关键是指令recursive_error_pages。我真正需要做的就是“打开”这个功能,我最初的想法就奏效了。这是我的 conf 的相关部分现在的样子:

server {
    ...

    root /var/www/someserver.com/;

    error_page 400 404      /404.html;
    error_page 500 502 504  /500.html;
    error_page 503          /503.html;

    recursive_error_pages   on;

    location ~* ^/(404\.html|500\.html|503\.html)$ {
        log_not_found off;
        error_page 404 = @default;
    }

    location @default {
        log_not_found on;
        root /var/www/default;
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里包含了不属于我的原始问题的其他错误类型,因为这最终导致我在 Martin F 的方法中遇到困难,否则它非常好。该log_not_found指令只是确保当在原始根目录中找不到错误页面时,我的日志中不会出现 404。

  • 您可能希望删除 `log_not_found off;` 并添加 `internal;`。 (2认同)

Mar*_*ald 5

try_files是去这里的方式。下面的配置应该可以工作,但我还没有测试它的语法错误。

server {
    ...
    root /var/www;

    location / {
        try_files /someserver.com$uri /default$uri /someserver.com$uri/ /default$uri/ @notfound;
    }

    location @notfound {
       try_files /someserver/404.html /default/404.html =404; # =404 should make it use the nginx-default 404 page.
    }
}
Run Code Online (Sandbox Code Playgroud)