Como configurar uma página de erro de fallback no nginx?

8

Estou configurando o processamento do nginx de algumas páginas de erro e outros arquivos de mídia "padrão" (como favicon.ico e robots.txt) no momento e me deparei com um problema menor para fazer as coisas funcionarem do jeito que eu quero determinadas páginas de erro.

Basicamente, o que estou tentando fazer é exibir determinados arquivos para um servidor na raiz desse servidor, por exemplo, /var/www/someserver.com/robots.txt. Se esse arquivo não existir, quero que o nginx vá para o "padrão", ou seja, /var/www/default/robots.txt. Esta é a essência básica de como eu tenho isso (com sucesso) configurado:

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

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

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

Isso funciona muito bem.

Estou tentando fazer o mesmo com as páginas de erro, mas não consigo fazer isso acontecer:

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

    error_page 404   /404.html;

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

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

Observe que isso "funciona" no sentido de que, se você visitar o site someserver.com/404.html, ele tentará primeiro carregar /var/www/someserver.com/404.html e depois voltar para / var / www / default / 404.html se não for encontrado. No entanto, se você visitar o site someserver.com/blahblah, ele mostrará apenas a página 404, se ela estiver configurada em /var/www/someserver.com/. Ele não volta para o diretório padrão se esse arquivo não existir.

De qualquer forma, você pode provavelmente o que eu estava tentando realizar (é por isso que incluí o primeiro exemplo de trabalho).

Alguma idéia?

Editar:

Com base na resposta de Martin F, foi o que acabei juntando:

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

Isso funciona incrível. O bloco real de error_pages e locais acima está em um arquivo server_defaults.conf que é incluído em cada host virtual, e é por isso que não codifiquei o caminho em cada localização e usou um caminho relativo para os padrões.

Editar 2:

Essa abordagem tem um problema. Se você fizer POST em um URL que retorna um erro, o método de solicitação POST será enviado com as tentativas try_files. Isso (para mim) resulta em um erro 405 Não permitido, porque o nginx está essencialmente tentando POST para, por exemplo. /default/500.html em vez de apenas pegar essa página.

Editar 3:

Eu postei uma solução que funciona muito mais próxima da minha ideia original.

    
por Jim D 25.03.2011 / 05:33

4 respostas

10

Acabei indo com algo muito mais próximo da minha ideia original. A chave que estava faltando acabou sendo a diretiva recursive_error_pages . Tudo o que eu realmente tive que fazer foi ligar isso e minha ideia original funcionou. Aqui está a parte relevante da minha conf agora:

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

Eu incluí outros tipos de erros que não faziam parte da minha pergunta original aqui, porque isso acabou me causando dificuldades com a abordagem de Martin F, que de outra forma era excelente. A diretiva log_not_found apenas garante que eu não obtenha 404s no meu log quando a página de erro não for encontrada na raiz original.

    
por 28.03.2011 / 15:32
5

try_files é o caminho a seguir aqui. A configuração a seguir deve funcionar, mas não testei erros de sintaxe.

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.
    }
}
    
por 25.03.2011 / 07:15
1

Infelizmente, estou alguns anos atrasado com a minha resposta, mas achei que isso poderia ajudar os futuros pesquisadores. Minha versão do Nginx instalada é 1.2.4, e eu criei o seguinte trecho de configuração,

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

}
    
por 02.01.2013 / 04:31
0

Eu achei que era crucial incluir "proxy_intercept_errors on"; em qualquer bloco de localização em que a error_page também foi incluída.

Sem essa configuração, o bloco de localização interceptará os códigos de erro que retornam do upstream.

link

    
por 03.02.2016 / 04:37

Tags