¿Cómo agrego encabezados sin caché a todas las 404 páginas servidas por apache y nginx?

9

Recientemente me he encontrado con un problema después de cambiar a Cloudflare, y la solución es básicamente evitar que Cloudflare almacene en caché las respuestas 404.

En nuestra configuración de varios servidores con equilibrio de carga, suceden ocasionalmente 404, pero rsync los soluciona rápidamente (a través de lsyncd). Antes de Cloudflare, una nueva solicitud al archivo 404ed se convertiría rápidamente en 200 a medida que rsync hace su trabajo.

Sin embargo, dado que Cloudflare almacena en caché todos los datos basados ​​en el encabezado de almacenamiento en caché, y ni apache ni nginx envían un encabezado sin caché para 404s, Cloudflare termina almacenando en caché la respuesta 404 por un tiempo.

He estado buscando una solución para agregar globalmente ese encabezado para 404s tanto en apache como en nginx (globalmente, para todos los dominios alojados), pero hasta ahora he quedado en blanco.

¿Alguien puede ayudar?

Gracias.

Artem Russakovskii
fuente
Pregunta similar, aunque solo para apache (todavía sin respuesta también): serverfault.com/questions/331544/… .
Artem Russakovskii
Hasta ahora, estoy bastante seguro de que no puede anular los encabezados devueltos por los manejadores 404 por defecto tanto en apache como en nginx (¡por favor demuestre que estoy equivocado!). Pude anular el controlador 404 y apuntarlo a un archivo PHP que envía tales encabezados en apache, pero dado que nginx no tiene soporte PHP en mi configuración, y la configuración "caduca -1; en la ubicación 404 no parecía hacer nada en realidad, todavía no sé cómo hacerlo en nginx.
Artem Russakovskii

Respuestas:

6

¿No puede usar una directiva error_page y luego manejar la ubicación por separado con el encabezado agregado?

Por ejemplo, en Nginx:

    server {
      ...
      error_page 404 /404.html;
      location = /404.html {
        root   /usr/share/nginx/html;
        add_header Cache-Control "no-cache" always;
      }
    }
jimmiw
fuente
1
Aquí hay dos problemas, pero esa es la dirección con la que fui. 1. No quería anular la página 404 predeterminada y tener que crear reglas en cada listenpuesto ya locationque no se admite httpdirectamente dentro . 2. Más importante aún, su fragmento en realidad no funciona porque add_header solo se aplica a 20X y 30X ( nginx.org/en/docs/http/ngx_http_headers_module.html ). Sin embargo, estamos de enhorabuena, ya que a partir del 1.7.5 lanzado recientemente, ahora puede agregar un alwaysmodificador que lo aplicará a todos los códigos de respuesta. Tuve que actualizar nginx pero fue una buena patada en el trasero. Funciona.
Artem Russakovskii
2
Actualicé mi respuesta, ¿quizás debería agregar una respuesta que muestre lo que hizo para resolver la pregunta?
Jimmiw
Parece que omitir rootfunciona también. Si eso se elimina, es más o menos lo que terminé haciendo para nginx.
Artem Russakovskii
Para apache, decidí que realmente quería usar una página personalizada, así que hice esto: ErrorDocument 404 /path/to/my/404.php. Y luego, dentro del 404.php, hice <? Php // no cachee el encabezado 404 ("Cache-Control: no-cache, must-revalidate"); // encabezado HTTP / 1.1 ("Caduca: sábado, 26 de julio de 1997, 05:00:00 GMT"); // ¿Fecha en el pasado?>
Artem Russakovskii
Estoy marcando su respuesta como aceptada. Si alguien quiere proporcionar una respuesta apache más genérica más tarde, o una respuesta nginx que funcione globalmente en lugar de por per server, puede recibir una votación positiva.
Artem Russakovskii
5

También puedes hacerlo de esta manera:

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


server {

    [ ... ]

    add_header "Cache-Control" $cache_header always;

}
Xavier Lucas
fuente
Inteligente. Probablemente voy a ir con la otra solución, ya que ya funciona y no requiere que se especifique un encabezado predeterminado de Cache-Control cada vez, pero esto fue pensar de manera innovadora.
Artem Russakovskii
Falta un punto y coma después, 404 "no-cache"pero la estúpida restricción de edición mínima de 6 caracteres de stackexchange me impide arreglarlo. Claramente no es una buena restricción para un sitio que se trata de codificación y configuraciones ...
nh2
3

En apache 2.4, puedes probar 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>

El alwayses importante porque este es un:

Está agregando un encabezado a una respuesta no exitosa generada localmente (no 2xx), como una redirección, en cuyo caso solo la tabla correspondiente a siempre se usa en la respuesta final.

Dijiste todos los 404, pero para una referencia completa, por supuesto, podría tener sentido envolver eso en <FilesMatch>o <LocationMatch>limitar el alcance.

Creo que esta es una nueva capacidad en Apache 2.4, ya que el uso de exprcondicionales no está en la versión 2.2 de la documentación de mod_headers.

curl -I [foo] prueba sin esta configuración:

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] prueba con esta configuración:

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

Fuentes:

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

cayleaf
fuente
0

mis cinco centavos sobre el tema

en nuestro proyecto PHP tenemos pocas páginas 404, así que decido hacerlo a nivel PHP usando las funciones de encabezado () de PHP

Mella
fuente