NodeJS / express: caché y código de estado 304

92

Cuando recargo un sitio web creado con express, obtengo una página en blanco con Safari (no con Chrome) porque el servidor NodeJS me envía un código de estado 304.

¿Cómo solucionar esto?

Por supuesto, esto también podría ser solo un problema de Safari, pero en realidad funciona bien en todos los demás sitios web, por lo que también tiene que ser un problema en mi servidor NodeJS.

Para generar las páginas, estoy usando Jade con res.render.

Actualización: parece que este problema se produce porque Safari envía una 'cache-control': 'max-age=0'recarga.

Actualización 2: ahora tengo una solución alternativa, pero ¿hay una solución mejor? Solución alterna:

app.get('/:language(' + content.languageSelector + ')/:page', function (req, res)
{
    // Disable caching for content files
    res.header("Cache-Control", "no-cache, no-store, must-revalidate");
    res.header("Pragma", "no-cache");
    res.header("Expires", 0);

    // rendering stuff here…
}

Actualización 3: la parte completa del código es actualmente:

app.get('/:language(' + content.languageSelector + ')/:page', pageHandle);

function pageHandle (req, res)
{
    var language = req.params.language;
    var thisPage = content.getPage(req.params.page, language);

    if (thisPage)
    {
        // Disable caching for content files
        res.header("Cache-Control", "no-cache, no-store, must-revalidate");
        res.header("Pragma", "no-cache");
        res.header("Expires", 0);

        res.render(thisPage.file + '_' + language, {
            thisPage : thisPage,
            language: language,
            languages: content.languages,
            navigation: content.navigation,
            footerNavigation: content.footerNavigation,
            currentYear: new Date().getFullYear()
        });
    }
    else
    {
        error404Handling(req, res);
    }
}
h345k34cr
fuente
1
304 no es un problema. Simplemente significa que su respuesta no se modifica y su navegador recurre al caché para buscar el recurso. ¿Puede publicar el código relevante en el que está ocurriendo la anomalía?
Akshat Jiwan Sharma
3
sí, en realidad no está modificado, pero Safari vacía su caché en CMD + R (recarga) y el servidor solo dice que no cambió.
h345k34cr
¿Cómo se relaciona la página en blanco con el código de estado 304? El nodo también enviaría 304 a otros navegadores.
user568109
2
Está relacionado porque con 304 el cuerpo no se envía y el navegador usa su caché, pero como no hay caché, obtienes una página en blanco
h345k34cr
1
@AkshatJiwanSharma Cualquier programa se desarrolla para cumplir exactamente con el contrato del propietario del producto. El propietario del producto es el que posee el código y paga el dinero, no una organización que escribe artículos que a nadie le importan. Si el contrato dice "200", cualquier estado que no sea igual a "200" es un error. Cuando hay un error, DEBO reescribir el código hasta que todo sea exactamente como se esperaba. El W3C no tiene nada que decir al respecto.
Gherman

Respuestas:

107

Solución más sencilla:

app.disable('etag');

Solución alternativa aquí si desea más control:

http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/

sangrando
fuente
2
¿Podría explicar la "solución más fácil" o dar una referencia sobre cómo afecta esto?
Samuel Méndez
1
@ SamuelMéndez básicamente deshabilita el almacenamiento en caché, el wiki en etag tiene mucha información buena en.wikipedia.org/wiki/HTTP_ETag
purgado el
Funcionó para mí :)
Naveen Kumar V
3

Como dijiste, Safari envía una Cache-Control: max-age=0recarga. Express (o más específicamente, la dependencia de Express, node-fresh) considera que la caché está obsoleta cuando Cache-Control: no-cachese reciben los encabezados, pero no hace lo mismo con Cache-Control: max-age=0. Por lo que puedo decir, probablemente debería. Pero no soy un experto en almacenamiento en caché.

La solución es el cambio (lo que es actualmente) línea 37 de node-fresh/index.jsde

if (cc && cc.indexOf('no-cache') !== -1) return false;  

a

if (cc && (cc.indexOf('no-cache') !== -1 ||
  cc.indexOf('max-age=0') !== -1)) return false;

Bifurqué node-fresh y express para incluir esta solución en la package.jsonvía de mi proyecto npm, podrías hacer lo mismo. Aquí están mis tenedores, por ejemplo:

https://github.com/stratusdata/node-fresh https://github.com/stratusdata/express#safari-reload-fix

La rama safari-reload-fix se basa en la etiqueta 3.4.7.

James P. Javery
fuente
¡Buen trabajo! Veo que express 3.5.1 incluye su solución a través de node-fresh 0.2.2.
Clafou
En realidad, estoy equivocado, su corrección se revirtió y no llegó a 0.2.2. Todavía no hay una solución nueva / rápida.
Clafou
2

Tuve el mismo problema en Safari y Chrome (los únicos que he probado) pero hice algo que parece funcionar, al menos no he podido reproducir el problema desde que agregué la solución. Lo que hice fue agregar una metaetiqueta al encabezado con una marca de tiempo generada. No parece correcto pero es simple :)

<meta name="304workaround" content="2013-10-24 21:17:23">

Actualizar PS Por lo que puedo decir, el problema desaparece cuando elimino mi proxy de nodo (por proxy me refiero al módulo express.vhost y http-proxy), lo cual es extraño ...

user907567
fuente
También utilizo un proxy Apache, este podría ser el problema. Mi solución fue simplemente deshabilitar el almacenamiento en caché para sitios de contenido con encabezados http.
h345k34cr
Deshabilitar la caché a través de los encabezados es definitivamente el camino a seguir. Al principio no me funcionó, pero ahora sí. En otras palabras, debo haber cometido un error en alguna parte de la primera vez :)
user907567
1

Intente utilizar la navegación privada en Safari o eliminar todo su caché / cookies.

Tuve algunos problemas similares al usar Chrome cuando el navegador pensó que tenía el sitio web en su caché pero en realidad no lo tenía.

La parte de la solicitud http que hace que el servidor responda un 304 es el etag. Parece que Safari está enviando el etag correcto sin tener el caché correspondiente.

sbugert
fuente
Eso
0

Vieja pregunta, lo sé. No es necesario desactivar la función de caché y no es la mejor manera de gestionar el problema. Al deshabilitar la función de caché, el servidor necesita trabajar más y genera más tráfico. Además, el navegador y el dispositivo deben trabajar más, especialmente en dispositivos móviles, esto podría ser un problema.

La página vacía se puede resolver fácilmente usando la tecla Shift + botón de recarga en el navegador.

La página vacía puede ser el resultado de:

  • un error en tu código
  • mientras probaba, mostró una página vacía (no puede recordar) que el navegador almacena en caché
  • un error en Safari (si es así, infórmalo a Apple y no intentes solucionarlo tú mismo)

Pruebe primero la tecla Shift + botón de recarga y vea si el problema persiste y revise su código.

Codebeat
fuente