1063 votes

Est Safari sur iOS 6 mise en cache de $.ajax résultats?

Depuis la mise à niveau vers iOS 6, nous voyons Safari vue web prendre la liberté de la mémoire cache, $.ajax des appels. C'est dans le contexte d'une application PhoneGap c'est donc à l'aide de Safari WebView. Notre $.ajax des appels sont POST méthodes et nous avons cache défini à false, {cache:false}, mais encore ce qui se passe. Nous avons essayé d'ajouter manuellement un timestamp pour les en-têtes, mais il n'a pas aidé.

Nous n'avons plus de recherches et découvert que Safari est seulement le retour de résultats mis en cache pour les services web qui ont une fonction de signature qui est statique et ne change pas d'un appel à l'. Imaginons, par exemple, une fonction appelée quelque chose comme:

getNewRecordID(intRecordType)

Cette fonction reçoit les mêmes paramètres d'entrée, encore et encore, mais les données qu'il retourne devrait être différent à chaque fois.

Doit être d'Apple dans la hâte pour faire iOS 6 zip le long d'une façon impressionnante, ils ont eu trop heureux avec les paramètres de cache. Quelqu'un d'autre a vu ce problème sur iOS 6? Si oui, quelle est exactement la cause?


La solution que nous avons trouvé a été de modifier la signature de la fonction pour être quelque chose comme ceci:

getNewRecordID(intRecordType, strTimestamp)

et puis toujours lui passer un paramètre timestamp, et juste à l'écart de la valeur sur le côté serveur. Cela fonctionne autour de la question. J'espère que cela aide certains autres pauvre âme qui consacre 15 heures sur cette question, comme je l'ai fait!

446voto

Kieran Points 3635

Après une petite enquête, il s'avère que Safari sur iOS6 met en cache les Messages qui n'ont pas d'-tête Cache-Control ou encore "Cache-Control: max-age=0".

Le seul moyen que j'ai trouvé de la prévention de cette mise en cache de passe à un niveau global plutôt que d'avoir à pirater aléatoire querystrings sur la fin des appels de service est de jeu de "Cache-Control: no-cache".

Donc:

  • Pas de Cache-Control ou Expire headers = iOS6 Safari cache
  • Cache-Control " max-age=0 et immédiate Expire = iOS6 Safari cache
  • Cache-Control: no-cache = iOS6 Safari NE cache

Je soupçonne que Apple est en train de profiter de ce à partir de la spécification HTTP dans la section 9.5 sur le POST:

Les réponses à cette méthode ne sont pas mis en cache, à moins que la réponse prévoit des mesures de Contrôle du Cache ou de l'Expiration de champs d'en-tête. Cependant, 303 (Voir d'Autres) réponse peut être utilisée pour diriger l'utilisateur de l'agent de récupérer un cache de ressources.

Donc, en théorie, vous pouvez mettre en cache POSTE de réponses...qui savait. Mais aucun autre navigateur maker a jamais pensé que ce serait une bonne idée jusqu'à maintenant. Mais qui ne prend PAS en compte pour la mise en cache lorsque aucun Cache-Control ou Expire en-têtes sont ensemble, seulement quand il y a un certain ensemble. Donc ça doit être un bug.

Ci-dessous est ce que j'utilise dans le droit peu de ma config d'Apache pour cible l'ensemble de mon API parce que, comme il arrive, je n'ai pas vraiment envie de cache quoi que ce soit, obtient même. Ce que je ne sais pas est de savoir comment définir ce juste pour les Messages.

Header set Cache-Control "no-cache"

Mise à jour: Viens de remarquer que je n'avais pas remarquer que c'est seulement lorsque le message est le même, afin de modifier les données POST ou l'URL et vous êtes fine. Ainsi, vous pouvez, comme le mentionne d'ailleurs qu'ajouter quelques données aléatoires à l'URL ou un peu de POST de données.

Mise à jour: Vous pouvez limiter le "no-cache" juste pour les Messages, si vous voulez, comme cela, dans Apache:

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

146voto

Dave Points 1201

J'espère que ce qui peut être utile à d'autres développeurs de se frapper la tête contre le mur sur celle-ci. J'ai trouvé que l'une des opérations suivantes empêche Safari sur iOS 6 de mise en cache de la réponse POST:

  • ajout de [cache-control: no-cache] dans les en-têtes de requête
  • l'ajout d'une variable en paramètre d'URL tels que l'heure actuelle
  • ajout de [pragma: no-cache] dans les en-têtes de réponse
  • ajout de [cache-control: no-cache] dans les en-têtes de réponse

Ma solution était la suivante dans mon Javascript (toutes mes requêtes AJAX sont POST).

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

J'ai aussi ajouter le [pragma: no-cache] en-tête pour beaucoup de mes réponses du serveur.

Si vous utilisez la solution ci-dessus sachez que tout $.ajax() appels qui sont mis à global: false, ne PAS utiliser les paramètres de dollars.ajaxSetup(), de sorte que vous aurez besoin d'ajouter les en-têtes de nouveau.

67voto

Baz1nga Points 10252

Solution Simple pour toutes vos demandes de service web, en supposant que vous êtes à l'aide de 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()
    }));
});

Lire plus sur le jQuery préfiltre appel ici.

Si vous n'êtes pas à l'aide de jQuery, consultez la documentation de votre bibliothèque de son choix. Ils peuvent avoir des fonctionnalités similaires.

43voto

Bashevis Points 751

J'ai juste eu ce problème aussi bien dans un PhoneGap application. Je l'ai résolu en utilisant la fonction JavaScript getTime() de la manière suivante:

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

J'ai perdu quelques heures de déterminer cela. Il aurait été agréable d'Apple pour informer les développeurs de ce problème de mise en cache.

42voto

Tadej Points 359

J'ai eu le même problème avec une webapp l'obtention de données de ASP.NET webservice

Cela a fonctionné pour moi:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X