Zwischenspeichert Safari unter iOS 6 $.ajax-Ergebnisse?

Lesezeit: 10 Minuten

Zwischenspeichert Safari unter iOS 6 ajax Ergebnisse
Benutzer1684978

Seit dem Upgrade auf iOS 6 sehen wir, dass sich die Webansicht von Safari die Freiheit des Cachings nimmt $.ajax Anrufe. Dies steht im Kontext einer PhoneGap-Anwendung, also wird Safari WebView verwendet. Unsere $.ajax Anrufe sind POST Methoden und wir haben den Cache auf false gesetzt {cache:false}, aber das passiert immer noch. Wir haben versucht, a manuell hinzuzufügen TimeStamp zu den Headern, aber es hat nicht geholfen.

Wir haben weitere Nachforschungen angestellt und festgestellt, dass Safari nur zwischengespeicherte Ergebnisse für Webdienste zurückgibt, deren Funktionssignatur statisch ist und sich nicht von Aufruf zu Aufruf ändert. Stellen Sie sich zum Beispiel eine Funktion vor, die so heißt:

getNewRecordID(intRecordType)

Diese Funktion erhält immer wieder die gleichen Eingabeparameter, aber die zurückgegebenen Daten sollten jedes Mal anders sein.

Muss in Apples Eile sein, iOS 6 beeindruckend zum Laufen zu bringen, sie waren mit den Cache-Einstellungen zu zufrieden. Hat jemand anderes dieses Verhalten auf iOS 6 gesehen? Wenn ja, woran genau liegt es?


Die Problemumgehung, die wir gefunden haben, bestand darin, die Funktionssignatur so zu ändern:

getNewRecordID(intRecordType, strTimestamp)

und dann immer in a übergehen TimeStamp -Parameter und verwerfen Sie diesen Wert einfach auf der Serverseite. Dies umgeht das Problem.

  • Das ist absolut schockierend. Wir haben auch gerade ein paar Stunden damit verbracht, herauszufinden, was gerade nicht mehr funktioniert. Unser AJAX-Login, das einen POST durchführt (und Header hat, um auch das Caching zu verhindern), wird von Safari zwischengespeichert, sodass es einfach dasselbe JSON zurückgibt wie beim letzten Mal, ohne den Server überhaupt zu testen … unglaublich! Wir müssen einen Fix hacken, aber Sie sollten niemals einen POST zwischenspeichern, es ist verrückt.

    – Kiran

    20. September 2012 um 14:55 Uhr

  • Veröffentlichen Sie Ihre Lösung als Antwort und nicht als Aktualisierung der Frage.

    – ChrisF

    21. September 2012 um 14:40 Uhr

  • POST-Anforderungen sind nicht idempotent, was bedeutet, dass sie nicht zwischengespeichert werden sollten wenn nicht die Antwort empfiehlt dies ausdrücklich über ihre Antwortheader.

    – James M. Greene

    21. September 2012 um 15:14 Uhr

  • Um Apple dazu zu bringen, dies zu beheben, melden Sie einen Fehler unter bugreport.apple.com. Ich habe das gleiche getan.

    – Mathias Bynens

    23. September 2012 um 10:13 Uhr


  • Mark Nottingham (Vorsitzender der IETF-HTTPbis-Arbeitsgruppe) hat heute einen interessanten Blogbeitrag darüber geschrieben: mnot.net/blog/2012/09/24/caching_POST

    – Benjamin Brizzi

    24. September 2012 um 15:02 Uhr

Zwischenspeichert Safari unter iOS 6 ajax Ergebnisse
Kieran

Nach ein wenig Nachforschung stellt sich heraus, dass Safari auf iOS6 POSTs zwischenspeichert, die entweder keine Cache-Control-Header oder sogar “Cache-Control: max-age=0” haben.

Die einzige Möglichkeit, die ich gefunden habe, um zu verhindern, dass dieses Caching auf globaler Ebene stattfindet, anstatt zufällige Abfragezeichenfolgen am Ende von Dienstaufrufen zu hacken, besteht darin, “Cache-Control: no-cache” festzulegen.

Damit:

  • Keine Cache-Control- oder Expires-Header = iOS6 Safari wird zwischengespeichert
  • Cache-Control max-age=0 und ein sofortiges Expires = iOS6 Safari wird cachen
  • Cache-Steuerung: no-cache = iOS6 Safari wird NICHT cachen

Ich vermute, dass Apple dies aus der HTTP-Spezifikation in Abschnitt 9.5 über POST ausnutzt:

Antworten auf diese Methode können nicht zwischengespeichert werden, es sei denn, die Antwort enthält entsprechende Cache-Control- oder Expires-Header-Felder. Die Antwort 303 (See Other) kann jedoch verwendet werden, um den Benutzeragenten anzuweisen, eine zwischenspeicherbare Ressource abzurufen.

Theoretisch können Sie also POST-Antworten zwischenspeichern … wer hätte das gedacht. Aber kein anderer Browser-Hersteller hat bisher jemals daran gedacht, dass dies eine gute Idee wäre. Dies berücksichtigt jedoch NICHT das Caching, wenn keine Cache-Control- oder Expires-Header festgelegt sind, sondern nur, wenn einige festgelegt sind. Es muss also ein Bug sein.

Unten ist, was ich im rechten Teil meiner Apache-Konfiguration verwende, um auf die gesamte API abzuzielen, da ich tatsächlich nichts zwischenspeichern möchte, auch nicht. Was ich nicht weiß, ist, wie man das nur für POSTs einstellt.

Header set Cache-Control "no-cache"

Update: Ich habe gerade bemerkt, dass ich nicht darauf hingewiesen habe, dass dies nur der Fall ist, wenn der POST gleich ist. Ändern Sie also die POST-Daten oder die URL, und es geht Ihnen gut. Sie können also, wie an anderer Stelle erwähnt, einfach einige zufällige Daten zur URL oder ein bisschen POST-Daten hinzufügen.

Update: Sie können den “No-Cache” nur auf POSTs beschränken, wenn Sie dies in Apache wünschen:

SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST

  • Ich verstehe, worauf Apple damit hinaus will, aber wir sehen zwischengespeicherte Antworten auf POST-Anforderungen, selbst wenn unsere Antworten keine Cache-Control- oder Expires-Header enthielten. In diesem Fall sollte iOS6 nicht jede Anfrage zwischenspeichern und senden. Dies geschieht nicht.

    – Kango_V

    20. September 2012 um 16:52 Uhr

  • Der von Ihnen zitierte Teil der HTTP-Spezifikation rechtfertigt nicht das Caching-Verhalten von iOS 6. Das Standardverhalten sollte sein, POST-Antworten nicht zwischenzuspeichern (dh wenn der “Cache-Control”-Header nicht definiert ist). Das Verhalten verstößt gegen die Spezifikation und sollte als Fehler betrachtet werden. Jeder, der XML/JSON-API-Webdienste erstellt, sollte seine POST-Antworten mit „Cache-control: no-cache“ ausstatten, um dieses Problem zu umgehen.

    – David H

    20. September 2012 um 23:06 Uhr

  • POST-Anforderungen sind nicht idempotent, was bedeutet, dass sie nicht zwischengespeichert werden sollten wenn nicht die Antwort empfiehlt dies ausdrücklich über ihre Antwortheader.

    – James M. Greene

    21. September 2012 um 15:13 Uhr


  • Wie David sagt, ist dies eine klare Verletzung des von Ihnen zitierten Satzes. Wenn es keine “Cache-Control- oder Expires-Header-Felder” gibt, sind entsprechende solche Header offensichtlich nicht enthalten. Ihre eigene Untersuchung zeigt jedoch, dass es in diesem Szenario zwischenspeichert. Bitte bearbeiten Sie Ihre Antwort.

    – Matthäus Flaschen

    22. September 2012 um 6:16 Uhr


  • Weiß jemand, wie lange das Ergebnis auf einem Gerät zwischengespeichert wird? Ich habe versucht, Safari zu beenden und mein Telefon neu zu starten, aber es ist immer noch zwischengespeichert. Ich weiß, dass es mit dem Löschen des Browser-Cache funktioniert, aber ich frage mich, wie lange es für Benutzer dauern wird, die das Problem einmal hatten, bevor es verschwindet. Nicht jeder wird daran denken, seinen Cache zu leeren …

    – Daniel Hallqvist

    25. September 2012 um 18:22 Uhr

Ich hoffe, dass dies für andere Entwickler von Nutzen sein kann, die hier ihren Kopf gegen die Wand schlagen. Ich habe festgestellt, dass eines der folgenden Dinge verhindert, dass Safari unter iOS 6 die POST-Antwort zwischenspeichert:

  • Hinzufügen [cache-control: no-cache] in den Request-Headern
  • Hinzufügen eines variablen URL-Parameters wie der aktuellen Uhrzeit
  • Hinzufügen [pragma: no-cache] in den Antwortheadern
  • Hinzufügen [cache-control: no-cache] in den Antwortheadern

Meine Lösung war die folgende in meinem Javascript (alle meine AJAX-Anfragen sind POST).

$.ajaxSetup({
    type: 'POST',
    headers: { "cache-control": "no-cache" }
});

Ich füge auch die hinzu [pragma: no-cache] Header zu vielen meiner Serverantworten.

Wenn Sie die obige Lösung verwenden, beachten Sie, dass alle von Ihnen getätigten $.ajax()-Aufrufe, die auf global: false gesetzt sind, NICHT die in $.ajaxSetup() angegebenen Einstellungen verwenden, sodass Sie die Header erneut hinzufügen müssen.

  • Dies ist DIE RICHTIGE Lösung für den Fehler. Der Fehler ist, dass iOS 6 POST-Anfragen aus seinem Cache bedient, anstatt sie an den Server zu senden. Der Fehler besteht nicht darin, dass Antworten von POST-Anforderungen zwischengespeichert werden (was zulässig ist). Wenn Sie weiterhin Antworten auf POST-Anforderungen für nachfolgende GET-Anforderungen an diesen URI aus dem Cache abrufen möchten, verwenden Sie diese Lösung.

    – Nikolaus Shanks

    12. November 2012 um 16:32 Uhr

  • Das funktioniert bei mir, aber ich verstehe nicht wie. Ich hatte bereits cache: false in meinem ajaxSetup angegeben, und wenn ich mir die Anforderungsheader ansehe, läuft das auf Cache-Control: no-cache und Pragma: no-cache hinaus – aber es wird immer noch auf dem iPad zwischengespeichert. Wenn ich dann Header hinzufüge: { “cache-control”: “no-cache” } in ajaxSetup, verdoppelt es den Cache-Control-Header zu “no-cache, no-cache” – und stoppt das Caching. Was passiert hier?

    – Tom W. Halle

    26. November 2012 um 22:18 Uhr

  • Funktioniert einwandfrei – man kann der Anfrage auch als Parameter $.ajax({type: ‘POST’, headers: { ‘cache-control’: ‘no-cache’ }, etc.}) hinzufügen

    – George Filippakos

    2. Januar 2013 um 13:05 Uhr

  • Was ist [pragma: no-cache]? Wofür wird der Pragmaschlüssel verwendet?

    – Zak-Tänze

    19. März 2013 um 20:34 Uhr

  • Ich denke auch, dass dies der beste Ansatz ist, anstatt eine Problemumgehung mit einem zusätzlichen Parameter. Wir haben dies nur bei den Anrufen hinzugefügt, wo wir es brauchten, für Anrufe, die immer die gleiche Antwort haben, ist das Caching wahrscheinlich eine gute Sache für den Endbenutzer.

    – deutschkiwi

    20. Mai 2013 um 22:37 Uhr

1645899677 411 Zwischenspeichert Safari unter iOS 6 ajax Ergebnisse
Baz1nga

Einfache Lösung für alle Ihre Webdienstanfragen, vorausgesetzt, Sie verwenden jQuery:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    // you can use originalOptions.type || options.type to restrict specific type of requests
    options.data = jQuery.param($.extend(originalOptions.data||{}, { 
      timeStamp: new Date().getTime()
    }));
});

Lesen Sie mehr über den jQuery-Vorfilteraufruf Hier.

Wenn Sie jQuery nicht verwenden, überprüfen Sie die Dokumentation für die Bibliothek Ihrer Wahl. Sie können ähnliche Funktionen haben.

  • Bei mir funktioniert es nicht, der Server antwortet: “Invalid primitive JSON: timeStamp” asp.net / iis 7.5

    – Alexandre

    24. September 2012 um 0:10 Uhr

  • Was ist mit $.ajax({ “cache”: false …}) ? wird es funktionieren, wenn es ein _= anhängt[TIMESTAMP]? (Ich besitze kein solches Gerät um es zu testen)

    – Karußell

    24. September 2012 um 12:59 Uhr


  • Ich habe eine vollständige Implementierung der von Karussell vorgeschlagenen Lösung gepostet. Siehe meine Antwort unten.

    – Sam Shiles

    27. September 2012 um 14:45 Uhr


  • @Karussell. Habe gerade versucht, $.ajax({ “cache”: false …}) zu setzen. Dadurch wird das Problem für POST-Anforderungen unter iOS6 nicht behoben. Vermutlich, weil JQuery gemäß ihrer Dokumentation davon ausgeht, dass kein Browser dumm genug ist, um Post-Requests zwischenzuspeichern. “Mit POST abgerufene Seiten werden nie zwischengespeichert, daher haben die Cache- und ifModified-Optionen in jQuery.ajaxSetup() keine Auswirkung auf diese Anfragen.”

    – Brett Hannah

    2. Oktober 2012 um 11:02 Uhr

  • Das funktioniert nicht. Post-Parameter werden nicht zusammengeführt. Der Beitrag von Dave ist eine bessere Lösung.

    – Chris Münch

    15. Oktober 2012 um 23:33 Uhr

1645899677 593 Zwischenspeichert Safari unter iOS 6 ajax Ergebnisse
Bashevis

Ich hatte dieses Problem auch gerade in a PhoneGap Anwendung. Ich habe es mit der JavaScript-Funktion gelöst getTime() auf folgende Art:

var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);

Ich habe ein paar Stunden damit verschwendet, das herauszufinden. Es wäre nett von Apple gewesen, die Entwickler über dieses Caching-Problem zu informieren.

Ich hatte das gleiche Problem mit einer Webapp, die Daten vom ASP.NET-Webservice erhielt

Das hat bei mir funktioniert:

public WebService()
{
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    ...
}

  • Danke sehr! Ich wurde verrückt, als ich versuchte herauszufinden, warum sich das iPhone so anders verhielt als jede andere Plattform. Diese ASP.NET-spezifische Lösung hat mir eine Menge Zeit gespart.

    – Mark Brittingham

    11. November 2012 um 18:14 Uhr

  • Hat unter iOS6 nicht funktioniert, siehe meine Antwort am Ende des Threads

    – Brian Ogden

    29. April 2013 um 6:41 Uhr

  • Bitte!!!! Setzen Sie eine Bedingung, um dies nur auf IOS 6 anzuwenden, der Inhaltscache ist für jede Anwendung von entscheidender Bedeutung.

    – Alexandre

    8. April 2015 um 22:27 Uhr

Endlich habe ich eine Lösung für mein Upload-Problem.

In JavaScript:

var xhr = new XMLHttpRequest();
xhr.open("post", 'uploader.php', true);
xhr.setRequestHeader("pragma", "no-cache");

Im PHP:

header('cache-control: no-cache');

  • Danke sehr! Ich wurde verrückt, als ich versuchte herauszufinden, warum sich das iPhone so anders verhielt als jede andere Plattform. Diese ASP.NET-spezifische Lösung hat mir eine Menge Zeit gespart.

    – Mark Brittingham

    11. November 2012 um 18:14 Uhr

  • Hat unter iOS6 nicht funktioniert, siehe meine Antwort am Ende des Threads

    – Brian Ogden

    29. April 2013 um 6:41 Uhr

  • Bitte!!!! Setzen Sie eine Bedingung, um dies nur auf IOS 6 anzuwenden, der Inhaltscache ist für jede Anwendung von entscheidender Bedeutung.

    – Alexandre

    8. April 2015 um 22:27 Uhr

Aus meinem eigenen Blogbeitrag iOS 6.0 speichert Ajax-POST-Anfragen:

So beheben Sie das Problem: Es gibt verschiedene Methoden, um das Caching von Anfragen zu verhindern. Die empfohlene Methode ist das Hinzufügen eines No-Cache-Headers. So wird es gemacht.

jQuery:

Suchen Sie nach iOS 6.0 und setzen Sie den Ajax-Header wie folgt:

$.ajaxSetup({ cache: false });

ZeptoJS:

Suchen Sie nach iOS 6.0 und setzen Sie den Ajax-Header wie folgt:

$.ajax({
    type: 'POST',
    headers : { "cache-control": "no-cache" },
    url : ,
    data:,
    dataType : 'json',
    success : function(responseText) {…}

Serverseitig

Java:

httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");

Stellen Sie sicher, dass Sie dies oben auf der Seite hinzufügen, bevor Daten an den Client gesendet werden.

.NETZ

Response.Cache.SetNoStore();

Oder

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

PHP

header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
header('Pragma: no-cache'); // HTTP 1.0.

  • Ein gutes No-Cache-Attribut für .NET stackoverflow.com/questions/10011780/…

    – Aran Mulholland

    21. November 2012 um 22:56 Uhr

866840cookie-checkZwischenspeichert Safari unter iOS 6 $.ajax-Ergebnisse?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy