如何在Nginx中设置后备错误页面?


10

目前,我正在配置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;
    }
}

效果很好。

我正在尝试对错误页面执行相同的操作,但是我无法做到这一点:

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

    error_page 404   /404.html;

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

    location @default {
        root /var/www/default;
    }
}

请注意,在您访问someserver.com/404.html的意义上,这种“工作方式”会首先尝试加载/var/www/someserver.com/404.html,然后回退到/ var / www / default /404.html(如果找不到)。但是,如果您访问someserver.com/blahblah,则仅在/var/www/someserver.com/中设置时才会显示404页面。如果该文件不存在,它不会退回到默认目录。

无论如何,您可能可以完成我想完成的工作(这就是为什么我包括了第一个工作示例)。

有任何想法吗?

编辑:

根据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;
    }
}

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

编辑2:

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

编辑3:

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

Answers:


10

最后我做了一个更接近我最初想法的事情。我缺少的钥匙原来是指令recursive_error_pages。我真正要做的就是将其打开,我的最初想法起作用了。这是我的会议的相关部分现在看起来像:

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;
    }
}

我在这里包括了其他错误类型,这些错误类型不是我原来的问题的一部分,因为这最终导致我在Martin F的方法上遇到了困难,否则效果非常好。该log_not_found指令只是确保当在原始根目录中找不到错误页面时,我不会在日志中得到404。


这可以很好地工作(尤其是404 / POST组合),但似乎吞没了HTTP错误代码并发送了200 ...您是否具有与我相同的行为?
10

2
您可能要删除log_not_found off;并添加internal;
Alix Axel

您在POST请求中发现的导致错误的问题是nginx的奇怪行为,请参阅trac.nginx.org/nginx/ticket/824
Robo

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.
    }
}

是的,这正是我所需要的。我曾经尝试过使用try_files,但是您的回答使我意识到我需要为其创建一个特殊的内部位置。我已经编辑了答案,以显示适合我的配置,该配置对您的建议进行了一些调整。
Jim D

请参阅上面的编辑2。据我所知,该建议不适用于POST请求。由于try_files使用原始请求的请求方法,因此最终得到405 Not Allowed响应。
Jim D

@JimD:好吧,您并没有完全使用这种方法,而是使用了一种经过修改的方法。这对我有用。如果Nginx二进制文件的版本早于0.8.x,请尝试进行升级
Martin Fjordvald 2011年

好吧,问题是我不仅仅使用404,这就是为什么我必须像现在一样执行error_page-> location-> try_files而不是location-> try_files-> location-> try_files的原因。但是,我使用的是来自软件包的0.7.x二进制文件,因此我将尝试从源代码构建它,并查看是否可以解决它。
Jim D

2

不幸的是,我的答案迟到了几年,但我认为这可能对将来的搜索者有所帮助。我安装的Nginx版本是1.2.4,并且创建了以下配置代码段,

server {

server_name www.example.com
root /var/www/example


## Errors -> Locations
error_page   400 /400.html;
error_page   403 /403.html;
error_page   404 /404.html;
error_page   500 502 503 504 /50x.html;

## Locations -> Fallback
location = /400.html {
    try_files /400.html @error;
    internal;
}
location = /403.html {
    try_files /403.html @error;
    internal;
}
location = /404.html {
    try_files /404.html @error;
    internal;
}
location = /50x.html {
    try_files /50x.html @error;
    internal;
}

## Fallback Directory
location @error {
    root /var/www/error;
}

}

1
善用internal
克林特·帕克

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.