Cómo comprobar si el estado de jQuery.ajax() request header es "304 Not Modified"?
http-status-code-304 (5)
Además, los encabezados se almacenarán en caché si la respuesta proviene de la memoria caché. Tomé esto como una oportunidad. Mi servidor envía un encabezado md5 único. Esto no tiene el mismo efecto que? Query = time (). Ahora, en el lado JS, verifique el último encabezado md5 con la corriente. Si recibe el mismo encabezado MD5 que antes, la respuesta proviene de la memoria caché. Olvidé todo sobre JQuery pero vi que es posible establecer y leer encabezados.
<?php
$oldMD5=filter_input(INPUT_SERVER,''HTTP_CONTENT_MD5'',int);
if(!empty($oldMD5)){
header(''Content-MD5: ''.(1+(int)$oldMD5));
}
--------------------------------------------------------------
<script>
var oldMD5=0;
//your Ajax implementation
Ajax.setRequestHeader(''Content-MD5'',''''+oldMD5);
var newMD5=parseInt(Ajax.getResponseHeader(''Content-MD5''),10);
if(newMD5 && oldMD5<newMD5,10){
oldMD5=newMD5;
//not cached
}else{
//cached
}
Esto es un poco abusivo, porque md5 debería ser un hash para verificar que los ''datos decodificados son los mismos que se enviaron inicialmente''.
Cómo comprobar si el estado de jQuery.ajax() request header es "304 Not Modified"?
jqXHR.status
generalmente devuelve 200
, incluso cuando el encabezado solicitado es "304 no modificado".
ifModified:true
no ayuda mucho porque rompe la solicitud de datos XHR.
Quizás intente esto?
$.ajax({
url: ''your-url'',
dataType: ''script'',
complete: function(xhr) {
if (xhr.status == 304) return;
// or better: if (xhr.status != 200) return;
// your code goes here
}
});
Sin manejar encabezados de caché manualmente, no es posible. Normalmente, 304 respuestas no están disponibles a través de la API de XHR :
Para 304 respuestas no modificadas que son el resultado de una solicitud condicional generada por el agente de usuario, el agente de usuario debe actuar como si el servidor diera una respuesta 200 OK con el contenido apropiado .
jQuery normalmente no sabe que hubo una respuesta 304, porque el navegador le dice amablemente mentiras a JavaScript sobre lo que realmente está sucediendo en la red.
Pero hay buenas noticias (más o menos): puede hacer que Ajax produzca una respuesta 304, pero solo configurando manualmente los encabezados de caché HTTP If-Modified-Since
o If-None-Match
en la solicitud:
El agente de usuario debe permitir que
setRequestHeader()
anule la validación automática de caché estableciendo encabezados de solicitud (por ejemplo,If-None-Match
,If-Modified-Since
), en cuyo caso se deben pasar 304 respuestas no modificadas.
Entonces, puedes usar código como:
var xhr = new XMLHttpRequest();
xhr.open("GET", "foo.html");
xhr.setRequestHeader("If-Modified-Since", "Fri, 15 Feb 2013 13:43:19 GMT");
xhr.send();
Una dificultad fundamental es cómo saber qué fecha de última modificación o ETag enviar? El navegador tiene información de caché que usa para enviar solicitudes, pero no comparte esa información con JavaScript. Afortunadamente, jQuery realiza un seguimiento de los encabezados Last-Modified
y ETag
de las respuestas de Ajax, por lo que puede usar ifModified:true
para que jQuery establezca esos valores de encabezado la próxima vez que envíe una solicitud para ese recurso.
Dos cosas para tener en cuenta sobre esto:
304 respuestas no llevan datos. Esto es por diseño. La suposición es que si ha elegido usar el almacenamiento en caché, ¡ debe tener una copia de los datos que ya están en su caché ! Si no obtiene ningún dato del servidor (es decir, porque todavía no tiene esos datos), ¿por qué está usando el almacenamiento en caché? El almacenamiento en caché debe usarse cuando tiene los datos antiguos disponibles y solo desea datos nuevos; por lo tanto, recuperar datos con un 304 no debería ser un problema.
jQuery debe tener una fecha de última modificación o un ETag (para usar con
If-None-Match
) almacenado a partir de una solicitud previa. El proceso es así:Primera búsqueda: jQuery no tiene información de caché, por lo que no envía
If-Modified-Since
oIf-None-Match
. Cuando la respuesta vuelve, el servidor puede anunciar una última modificación de datos o una ETag, que jQuery almacena para su uso futuro.Recuperaciones posteriores: jQuery tiene información de caché de la última recuperación y reenvía esos datos al servidor. Si el recurso no ha cambiado, la solicitud de Ajax obtiene una respuesta 304. Si el recurso ha cambiado, la solicitud de Ajax obtiene una respuesta de 200, junto con la nueva información de caché que jQuery usará para su próxima búsqueda.
jQuery no persiste información de caché (por ejemplo, en cookies) entre recargas de página, sin embargo. Por lo tanto, la primera extracción de un recurso después de una recarga de página nunca será un 304, porque jQuery no tiene información de caché para enviar (es decir, volvemos al caso de "primera búsqueda"). No hay ninguna razón por la cual jQuery no pudo conservar la información de la memoria caché, pero en este momento no es así.
La conclusión es que puede usar encabezados de caché para obtener una respuesta JavaScript 304, pero no puede acceder a la propia ETag del navegador ni a la fecha de última modificación de un recurso en particular. Por lo tanto, es posible que el navegador conozca información sobre el almacenamiento en caché de un recurso, pero su código JavaScript no. En ese caso, el navegador usará sus encabezados de caché para obtener potencialmente una respuesta 304 real, pero reenvía una respuesta de 200 a su código JavaScript, porque JavaScript no envió ninguna información de caché.
No es posible hacer que las solicitudes de JavaScript 304 se alineen perfectamente con las respuestas reales de la red 304, porque la información de caché conocida por su navegador y la información de caché conocida por su código JavaScript pueden diferir en formas impredecibles. Sin embargo, obtener 304 solicitudes correctamente la mayor parte del tiempo es suficiente para la mayoría de las necesidades de desarrollo práctico.
Ejemplo
Aquí hay un breve ejemplo de servidor escrito en Node.js (pero debería ser lo suficientemente simple como para portarlo a otros lenguajes):
require("http").createServer(function (req, res) {
console.log(req.headers["if-modified-since"]);
// always send Last-Modifed header
var lastModDate = "Fri, 13 Feb 2013 13:43:19 GMT";
res.setHeader("Last-Modified", lastModDate);
// if the request has a If-Modified-Since header,
// and it''s newer than the last modification,
// then send a 304 response; otherwise send 200
if(req.headers["if-modified-since"] &&
Date.parse(lastModDate) <= Date.parse(req.headers["if-modified-since"])) {
console.log("304 -- browser has it cached");
res.writeHead(304, {''Content-Type'': ''text/plain''});
res.end();
} else {
console.log("200 -- browser needs it fresh");
res.writeHead(200, {''Content-Type'': ''text/plain''});
res.end(''some content'');
}
}).listen(8080);
Al ejecutar este servidor, puede cargar la página en su navegador y realizar dos pruebas diferentes en la consola de su navegador:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }
Esta secuencia de comandos siempre verá una respuesta de 200
, incluso si el navegador proporciona un encabezado de solicitud If-Modified-Since
y obtiene un 304
(que pasará todas las solicitudes después de la primera, después de que el navegador vea el encabezado de respuesta Last-Modifed
del servidor).
Por el contrario, este script siempre verá la respuesta 304:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.setRequestHeader("If-Modified-Since", "Fri, 15 Feb 2013 13:43:19 GMT");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }
El script proporciona su propio encabezado de solicitud If-Modified-Since
(dos días después de la fecha de última modificación del servidor); no depende de lo que el navegador suministre para If-Modified-Since
, y por lo tanto está permitido (según la especificación XHR) ver 304 respuestas.
Finalmente, este script siempre verá un 200
:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.setRequestHeader("If-Modified-Since", "Fri, 12 Feb 2013 13:43:19 GMT");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }
Esto se debe a que el script utiliza un If-Modified-Since
anterior a la última fecha de modificación del servidor, por lo que el servidor siempre envía un 200
. El servidor no enviará un 304
porque supone que el cliente no tiene una copia almacenada en caché de la versión más reciente (es decir, el cliente anuncia que ha visto cambios desde el 12 de febrero, pero el 13 de febrero hubo un cambio en que el cliente aparentemente no ha visto).
Tengo algún tipo de implementación en https://github.com/laukstein/ajax-seo/blob/cbed03222d89f6f7e75dc49ce8882c30201bbb86/index.php#L266-274
var cache;
$.ajax({
...
beforeSend: function() {
cache = setTimeout(function() {
console.log(''The content not cached jet.'');
}, 300);
},
success: function(data) {
if (cache) {
clearTimeout(cache);
}
}
});
abre el inspector de tu navegador y te mostrará información sobre la solicitud de AJAX, incluido el estado.
para Chrome, haga clic derecho y elija inspeccionar elemento, luego vaya a la pestaña Red.
para Firefox, solo usa Firebug y sigue los mismos pasos.