Como adiciono cabeçalhos sem cache a todas as 404 páginas servidas pelo apache e nginx?

9

Recentemente, encontrei um problema depois de mudar para o Cloudflare, e a solução é basicamente impedir o Cloudflare de armazenar em cache as respostas 404.

Em nossa configuração de vários servidores com balanceamento de carga, ocorrem 404 ocasionais, mas são rapidamente corrigidos pelo rsync (via lsyncd). Antes do Cloudflare, uma solicitação novamente para o arquivo 404ed se tornaria muito rapidamente 200 quando o rsync fizer seu trabalho.

No entanto, como o Cloudflare armazena em cache todos os dados com base no cabeçalho de cache e nem o apache nem o nginx enviam um cabeçalho sem cache para 404s, o Cloudflare acaba armazenando em cache a resposta 404 por um tempo.

Estive procurando uma solução para adicionar globalmente esse cabeçalho para 404s no apache e no nginx (globalmente, para todos os domínios hospedados), mas até agora ficaram em branco.

Alguém pode ajudar?

Obrigado.

Artem Russakovskii
fonte
Pergunta semelhante, embora apenas para o apache (ainda sem resposta): serverfault.com/questions/331544/… .
Artem Russakovskii
Até agora, tenho certeza de que você não pode substituir os cabeçalhos retornados pelos manipuladores 404 padrão no apache e no nginx (por favor, prove que estou errado!). Consegui substituir o manipulador 404 e apontá-lo para um arquivo PHP que envia esses cabeçalhos no apache, mas como o nginx não tem suporte ao PHP na minha configuração, e a configuração "expires -1;" no local 404, na verdade, não parecia fazer nada, ainda estou sem saber como fazer isso no nginx.
Artem Russakovskii

Respostas:

6

Você não consegue usar uma diretiva error_page e, em seguida, manipula o local separadamente com o cabeçalho adicionado?

por exemplo, no Nginx:

    server {
      ...
      error_page 404 /404.html;
      location = /404.html {
        root   /usr/share/nginx/html;
        add_header Cache-Control "no-cache" always;
      }
    }
jimmiw
fonte
1
Há duas questões aqui, mas essa foi a direção que segui. 1. Eu não queria substituir a página 404 padrão e tenho que criar regras a cada listenvez que locationnão é suportada httpdiretamente por dentro . 2. Mais importante, seu snippet realmente não funciona porque add_header se aplica apenas a 20X e 30X ( nginx.org/en/docs/http/ngx_http_headers_module.html ). No entanto, estamos com sorte, já que a partir do 1.7.5 lançado recentemente, agora você pode adicionar um alwaysmodificador que o aplicará a todos os códigos de resposta. Eu tive que atualizar o nginx, mas foi um bom chute na bunda. Funciona.
Artem Russakovskii
2
Eu atualizei minha resposta, talvez você devesse adicionar uma resposta mostrando o que você fez para resolver a pergunta?
Jimmiw
Parece que a omissão também rootfunciona. Se isso for removido, é praticamente o que acabei fazendo pelo nginx.
Artem Russakovskii
Para o apache, decidi que realmente queria usar uma página personalizada, e fiz o seguinte: ErrorDocument 404 /path/to/my/404.php. E então dentro do 404.php, eu <? Php // não coloco em cache o cabeçalho 404 ("Cache-Control: no-cache, must-revalidate"); // cabeçalho HTTP / 1.1 ("Expira: Sáb, 26 de julho de 1997 05:00:00 GMT"); // Data no passado?>
Artem Russakovskii
Estou marcando sua resposta como aceita. Se alguém quiser fornecer uma resposta apache mais genérica posteriormente, ou uma nginx que funcione globalmente e não por serverela, poderá ser votada.
Artem Russakovskii
5

Você também pode fazer o seguinte:

map $status $cache_header {
    default <for_other_codes>;
    404     "no-cache";
}


server {

    [ ... ]

    add_header "Cache-Control" $cache_header always;

}
Xavier Lucas
fonte
Inteligente. Provavelmente vou usar a outra solução, já que ela já funciona e não exige que um cabeçalho de controle de cache padrão seja especificado todas as vezes, mas isso era algo que estava fora da caixa.
Artem Russakovskii
Falta um ponto-e-vírgula depois, 404 "no-cache"mas a estúpida restrição de edição de 6 caracteres da stackexchange me impede de corrigi-la. Claramente, não é uma boa restrição para um site que tem tudo a ver com codificação e configurações ...
nh2 3/17
3

No apache 2.4, você pode tentar algo como:

FileETag None
<IfModule mod_headers.c>
    Header always unset ETag "expr=%{REQUEST_STATUS} == 404"
    Header always set Cache-Control "max-age=0, no-cache, no-store, must-revalidate" "expr=%{REQUEST_STATUS} == 404"
    Header always set Pragma "no-cache" "expr=%{REQUEST_STATUS} == 404"
    Header always set Expires "Wed, 11 Jan 1984 05:00:00 GMT" "expr=%{REQUEST_STATUS} == 404"
</IfModule>

O alwaysé importante porque este é um:

Você está adicionando um cabeçalho a uma resposta não-sucesso (não-2xx) gerada localmente, como um redirecionamento; nesse caso, apenas a tabela correspondente a sempre é usada na resposta final.

Você disse todos os 404s, mas para uma referência completa, é claro, pode fazer sentido colocar isso em um <FilesMatch>ou <LocationMatch>limitar o escopo.

Eu acredito que este é um novo recurso no apache 2.4, pois o uso de exprcondicionais não é o da versão 2.2 da documentação do mod_headers.

curl -I [foo] teste sem esta configuração:

HTTP/1.1 404 Not Found
Date: Thu, 24 May 2018 17:44:29 GMT
Server: Apache/2.4.18 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1

curl -I [foo] teste com esta configuração:

HTTP/1.1 404 Not Found
Date: Thu, 24 May 2018 17:44:42 GMT
Server: Apache/2.4.18 (Ubuntu)
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Content-Type: text/html; charset=iso-8859-1

Fontes:

http://httpd.apache.org/docs/current/mod/mod_headers.html

cayleaf
fonte
0

meus cinco centavos na questão -

em nosso projeto PHP, temos poucas páginas 404, então eu decido fazê-lo no nível PHP usando as funções header () do PHP

usuario
fonte