Come verificare se lo stato dell’intestazione della richiesta jQuery.ajax () è “304 non modificato”?

Come verificare se lo stato dell’intestazione della richiesta jQuery.ajax () è “304 non modificato”?

jqXHR.status solito restituisce 200 , anche quando l’intestazione richiesta è “304 Not Modified”.

ifModified:true non aiuta molto perché interrompe la richiesta di dati XHR.

Senza gestire le intestazioni della cache manualmente, non è ansible. Normalmente, 304 risposte non sono rese disponibili tramite l’ API XHR :

Per le risposte 304 non modificate che sono il risultato di una richiesta condizionale generata da un agente utente, l’agente utente deve comportarsi come se il server avesse dato una risposta di 200 OK con il contenuto appropriato .

jQuery normalmente non sa che c’è stata una risposta 304, perché il browser dice bugie bugie a JavaScript su ciò che sta realmente accadendo sulla rete.

Ma c’è una buona notizia (tipo di): puoi ottenere Ajax per produrre una risposta 304, ma solo impostando manualmente le intestazioni della cache HTTP If-Modified-Since o If-None-Match nella richiesta:

L’ setRequestHeader() deve consentire a setRequestHeader() di sovrascrivere la convalida automatica della cache impostando le intestazioni delle richieste (ad esempio, If-None-Match , If-Modified-Since ), nel qual caso devono passare le risposte 304 Non Modificate.

Quindi, puoi usare un codice come:

 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 difficoltà fondamentale è come fai a sapere quale data dell’ultima modifica o ETag inviare? Il browser ha informazioni sulla cache che utilizza per l’invio di richieste, ma non condividerà tali informazioni con JavaScript. Fortunatamente, jQuery tiene traccia degli header Last-Modified e ETag dalle risposte Ajax, quindi puoi utilizzare ifModified:true per avere jQuery impostare quei valori di intestazione la prossima volta che invia una richiesta per quella risorsa.

Due cose da notare su questo:

  • 304 risposte non portano dati. Questo è di design. L’ipotesi è che se hai scelto di usare la cache, dovresti avere una copia dei dati già nella tua cache ! Se ottenere dati dal server non è un problema (ad es., Perché non hai già quei dati) perché stai usando la cache? Il caching dovrebbe essere usato quando si hanno a disposizione i vecchi dati e vogliono solo nuovi dati; quindi, non tornare indietro con un 304 non dovrebbe essere un problema.

  • jQuery deve avere una data di ultima modifica o un ETag (da utilizzare con If-None-Match ) memorizzati da una richiesta precedente. Il processo è così:

    • Primo recupero: jQuery non ha informazioni sulla cache, quindi non invia If-Modified-Since o If-None-Match . Quando la risposta ritorna, il server può annunciare un ultimo dato modificato o un ETag, che jQuery memorizza per uso futuro.

    • Fetch successivi: jQuery ha informazioni di cache dall’ultimo recupero e inoltra tali dati al server. Se la risorsa non è stata modificata, la richiesta Ajax ottiene una risposta 304. Se la risorsa è cambiata, la richiesta Ajax riceve una risposta 200, insieme a nuove informazioni sulla cache per jQuery da utilizzare per il successivo recupero.

    • jQuery tuttavia non conserva le informazioni della cache (ad es. nei cookie) tra ricariche di pagina. Pertanto, il primo recupero di una risorsa dopo il ricaricamento di una pagina non sarà mai un 304, perché jQuery non ha informazioni sulla cache da inviare (cioè, ripristiniamo il caso “primo recupero”). Non c’è alcun motivo per cui jQuery non possa persistere nella cache delle informazioni, ma al momento no.

La linea di fondo qui è che è ansible utilizzare le intestazioni della cache per ottenere una risposta JavaScript 304, ma non è ansible accedere al proprio ETag o alla data dell’ultima modifica del browser per una particolare risorsa. Quindi, il browser stesso potrebbe conoscere le informazioni di cache su una risorsa, ma il tuo codice JavaScript no. In tal caso, il browser utilizzerà le intestazioni della cache per ottenere potenzialmente una risposta 304 reale, ma inoltrerà una risposta di 200 al codice JavaScript, poiché JavaScript non ha inviato alcuna informazione sulla cache.

Non è ansible rendere le richieste di JavaScript 304 allineate perfettamente con le risposte effettive della rete 304, poiché le informazioni sulla cache note dal browser e le informazioni sulla cache note dal codice JavaScript potrebbero differire in modi imprevedibili. Tuttavia, ottenere 304 richieste correttamente per la maggior parte del tempo è sufficiente per la maggior parte delle esigenze di sviluppo pratico.

Esempio

Ecco un breve esempio di server scritto in Node.js (ma dovrebbe essere abbastanza semplice da portarlo su altri linguaggi):

 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); 

Quando si esegue questo server, è ansible caricare la pagina nel browser ed eseguire due diversi test nella console del browser:

 var xhr = new XMLHttpRequest(); xhr.open("GET", "/"); xhr.send(); xhr.onload = function() { console.log(xhr.status); } 

Questo script vedrà sempre una risposta 200 , anche se il browser fornisce un'intestazione di richiesta If-Modified-Since e ottiene un 304 (che avverrà tutte le richieste dopo la prima, dopo che il browser vede l'intestazione di risposta Last-Modifed del server).

Al contrario, questo script vedrà sempre 304 risposte:

 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); } 

Lo script fornisce la propria intestazione della richiesta If-Modified-Since (due giorni dopo la data dell'ultima modifica del server); non si basa su ciò che il browser fornisce per If-Modified-Since , e quindi è consentito (secondo le specifiche XHR) di vedere 304 risposte.

Infine, questo script vedrà sempre 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); } 

Questo perché lo script utilizza un If-Modified-Since che è precedente alla data dell'ultima modifica del server, quindi il server invia sempre un 200 . Il server non invierà un 304 perché si presuppone che il client non abbia una copia cache della versione più recente (cioè, il client annuncia che sono stati visti cambiamenti dal 12 febbraio, ma il 13 febbraio c'è stata una modifica del client apparentemente non ha visto).

Anche le intestazioni verranno memorizzate nella cache se la risposta proviene dalla cache. Ho preso questo come una possibilità. Il mio server invia un’intestazione md5 univoca. Questo non ha lo stesso effetto come? Query = time (). Ora sul lato JS verifica l’ultima intestazione md5 con la corrente. Se si riceve la stessa intestazione MD5 come prima, la risposta proviene dalla cache. Ho dimenticato tutto su JQuery ma ho visto che è ansible impostare e leggere le intestazioni.

  var oldMD5=0; //your Ajax implementation Ajax.setRequestHeader('Content-MD5',''+oldMD5); var newMD5=parseInt(Ajax.getResponseHeader('Content-MD5'),10); if(newMD5 && oldMD5 

Questo è un po 'abusato, perché md5 dovrebbe essere un hash per verificare che i' dati decodificati siano gli stessi dati inizialmente inviati '.

Ho una specie di implementazione in 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); } } }); 

Forse provarlo?

 $.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 } }); 

apri l’ispettore del tuo browser e ti mostrerà le informazioni sulla richiesta Ajax, compreso lo stato.

per chrome, fai clic con il pulsante destro del mouse e seleziona inspect element, quindi vai alla scheda Network.

per Firefox, basta usare firebug e seguire la stessa procedura.