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.