Pregunta ¿Safari en iOS 6 almacena en caché los resultados $ .ajax?


Desde la actualización a iOS 6, estamos viendo que la vista web de Safari se toma la libertad de almacenar en caché $.ajax llamadas. Esto es en el contexto de una aplicación PhoneGap por lo que está usando Safari WebView. Nuestra $.ajax las llamadas son POST métodos y tenemos el caché establecido en falso {cache:false}, pero aún esto está sucediendo. Intentamos agregar manualmente un TimeStamp a los encabezados, pero no ayudó.

Hicimos más investigaciones y descubrimos que Safari solo está devolviendo resultados en caché para servicios web que tienen una firma de función que es estática y no cambia de llamada a llamada. Por ejemplo, imagine una función llamada algo así como:

getNewRecordID(intRecordType)

Esta función recibe los mismos parámetros de entrada una y otra vez, pero los datos que devuelve deben ser diferentes cada vez.

Debe estar a la prisa de Apple para hacer que el iOS 6 se borre a lo largo de manera impresionante. Se pusieron muy contentos con la configuración de caché. ¿Alguien más ha visto este comportamiento en iOS 6? Si es así, ¿qué es exactamente lo que está causando?


La solución alternativa que encontramos fue modificar la firma de la función para que fuera algo como esto:

getNewRecordID(intRecordType, strTimestamp)

y luego siempre pasa en una TimeStamp parámetro también, y simplemente descartar ese valor en el lado del servidor. Esto funciona alrededor del problema. ¡Espero que esto ayude a otra pobre alma que pasa 15 horas en este tema como yo!


1029
2017-09-20 06:07


origen


Respuestas:


Después de un poco de investigación, resulta que Safari en iOS6 guardará en caché los POST que no tienen encabezados de Cache-Control o incluso "Cache-Control: max-age = 0".

La única forma que he encontrado de evitar que este almacenamiento en caché ocurra a nivel global en lugar de tener que hackear cadenas de búsqueda aleatorias al final de las llamadas de servicio es establecer "Cache-Control: no-cache".

Asi que:

  • Sin encabezados Cache-Control o Expires = iOS6 Safari guardará en caché
  • Cache-Control max-age = 0 y una caducidad inmediata de Expires = iOS6 Safari
  • Cache-Control: no-cache = iOS6 Safari NO guardará en caché

Sospecho que Apple está aprovechando esto de las especificaciones de HTTP en la sección 9.5 sobre POST:

Las respuestas a este método no son guardables, a menos que la respuesta      incluye los campos de encabezado Cache-Control o Expires adecuados. Sin embargo,      la respuesta 303 (Ver Otro) se puede usar para dirigir al agente usuario a      recuperar un recurso almacenable en caché

Entonces, en teoría, puede almacenar en caché las respuestas POST ... quién sabe. Pero ningún otro navegador ha pensado que sería una buena idea hasta ahora. Pero eso NO tiene en cuenta el almacenamiento en caché cuando no están configurados los encabezados Cache-Control o Expires, solo cuando hay algún conjunto. Entonces debe ser un error.

A continuación se muestra lo que uso en el bit correcto de mi configuración de Apache para apuntar a la totalidad de mi API porque, en realidad, no quiero guardar nada en la memoria caché, incluso lo hace. Lo que no sé es cómo configurar esto solo para los POST.

Header set Cache-Control "no-cache"

Actualización: Me acabo de dar cuenta de que no señalé que es solo cuando el POST es el mismo, así que cambie cualquiera de los datos POST o URL y estará bien. De modo que puede, como se mencionó en otra parte, agregar algunos datos aleatorios a la URL o un poco de datos POST.

Actualización: puede limitar el "no-caché" solo a POST si desea esto en Apache:

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

434
2017-09-20 16:06



Espero que esto pueda ser útil para otros desarrolladores golpeando su cabeza contra la pared en este caso. Descubrí que cualquiera de los siguientes impide que Safari en iOS 6 guarde en caché la respuesta POST:

  • agregando [cache-control: no-cache] en los encabezados de solicitud
  • agregar un parámetro URL variable como la hora actual
  • agregando [pragma: no-cache] en los encabezados de respuesta
  • agregando [cache-control: no-cache] en los encabezados de respuesta

Mi solución fue la siguiente en mi Javascript (todas mis solicitudes AJAX son POST).

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

También agrego el encabezado [pragma: no-cache] a muchas de las respuestas de mi servidor.

Si usa la solución anterior, tenga en cuenta que cualquier llamada a $ .ajax () que realice se configurará como global: false NO utilizará la configuración especificada en $ .ajaxSetup (), por lo que deberá agregar los encabezados nuevamente.


143
2017-10-12 09:56



Solución simple para todas sus solicitudes de servicio web, suponiendo que esté utilizando 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()
    }));
});

Obtenga más información sobre la llamada de prefiltro jQuery aquí.

Si no está utilizando jQuery, consulte los documentos de su biblioteca de su elección. Pueden tener una funcionalidad similar.


64
2017-09-21 08:53



Tuve el mismo problema con una aplicación de Internet que obtiene datos del servicio web ASP.NET

Esto funcionó para mí:

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

40
2017-09-20 21:28



Acabo de tener este problema también en una PhoneGap solicitud. Lo solucioné usando la función de JavaScript getTime() en la siguiente manera:

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

Perdí unas horas averiguando esto. Hubiera sido bueno de Apple notificar a los desarrolladores de este problema de almacenamiento en caché.


40
2017-09-20 07:34



Finalmente, tengo una solución para mi problema de carga.

En JavaScript:

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

En PHP:

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

22
2017-09-22 10:16



De mi propia publicación en el blog iOS 6.0 caché de solicitudes AJAX POST:

Cómo solucionarlo: existen varios métodos para evitar el almacenamiento en caché de las solicitudes. El método recomendado es agregar un encabezado sin memoria caché. Así es como se hace.

jQuery:

Comprueba iOS 6.0 y configura el encabezado Ajax así:

$.ajaxSetup({ cache: false });

ZeptoJS:

Verifique iOS 6.0 y configure el encabezado Ajax así:

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

Lado del servidor

Java:

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

Asegúrese de agregar esto en la parte superior de la página antes de enviar los datos al cliente.

.RED

Response.Cache.SetNoStore();

O

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.

14
2017-11-14 06:02