Sin manejar los encabezados de caché manualmente, no es posible. Normalmente, 304 respuestas no se ponen a disposición a través de la XHR API:
Por 304 Not Modified respuestas que son el resultado de un agente de usuario genera la solicitud condicional el agente de usuario debe actuar como si el servidor dio una respuesta 200 OK con el contenido apropiado.
jQuery normalmente no sabe que hubo una respuesta 304, porque el navegador le dice mentiras a JavaScript sobre lo que está sucediendo realmente en la red.
Pero hay buenas noticias (tipo de): se puede obtener Ajax para producir una respuesta 304, pero sólo manualmente ajustando el HTTP cache headersIf-Modified-Since
o If-None-Match
en la solicitud:
El agente de usuario debe Permitir setRequestHeader()
para anular la validación automática de caché mediante el establecimiento de encabezados de solicitud (por ejemplo, If-None-Match
, If-Modified-Since
), en cuyo caso se deben pasar 304 respuestas no modificadas.
Por lo tanto, se puede utilizar un 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 para enviar? El navegador tiene información de caché que utiliza para enviar solicitudes, pero no compartirá 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 a tener en cuenta sobre esta
:
304 respuestas no transportan datos. Esto es por diseño. La suposición es que si ha elegido usar el almacenamiento en caché, ¡debería 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 esa información), ¿por qué está utilizando 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 de una solicitud anterior. El proceso es el siguiente:
Primera tomará: jQuery no tiene información de caché, por lo que no envía If-Modified-Since
o If-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 persisten la información de caché (por ejemplo, en las cookies) entre recargas de página, sin embargo. Por lo tanto, la primera recuperación de un recurso después de una recarga de página será nunca sea un 304, porque jQuery no tiene información de caché para enviar (es decir, reiniciamos 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í.
El fondo aquí es que se puede utilizar cabeceras de caché para obtener una respuesta JavaScript 304, pero no se puede acceder propia ETag o fecha de última modificación del navegador de un recurso en particular. Por lo tanto, es posible que el navegador conozca información de almacenamiento en caché sobre 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 304 respuestas reales de la red, 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
He aquí un breve ejemplo de servidor escrito en Node.js (pero debe ser lo suficientemente simple para un puerto con otros langauges):
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);
Cuando se ejecuta este servidor, puede cargar la página en su navegador y realizar dos pruebas diferentes en su consola de navegador:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/");
xhr.send();
xhr.onload = function() { console.log(xhr.status); }
Este script siempre verán una respuesta 200
, incluso si el navegador s actualiza un encabezado de solicitud If-Modified-Since
y obtiene un 304
(que sucederá a todas las solicitudes después de la primera, después de que el navegador vea el encabezado de respuesta del servidor Last-Modifed
).
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 guión suministra su propia cabecera If-Modified-Since
petición (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.
Por último, 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 la secuencia de comandos utiliza un If-Modified-Since
que es anterior a la fecha de última modificación del servidor, por lo que el servidor siempre envía una 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).
La respuesta corta es no. Sin embargo, este es un posible duplicado de [Determinando qué jQuery .ajax() resuelve una cadena de redireccionamientos a] (http://stackoverflow.com/questions/6767618/determining-what-jquery-ajax-resolves-a-string- of-redirects-to) Aunque no es exactamente la misma pregunta, el concepto es el mismo: la especificación XHR no requiere ninguna notificación de respuestas 3xx. – JAAulde
Vale la pena señalar que no es necesario hacer la verificación de ETag manualmente, desde su javascript, el navegador lo manejará por usted. Entonces, a menos que tenga una razón especial para hacerlo, generalmente no necesita verificar la respuesta 304 – Anentropic