自从升级到iOS 6之后,我们看到Safari的web视图冒昧地缓存了$.ajax
调用。这是在PhoneGap应用程序的上下文中进行的,因此它使用的是Safari WebView。我们的$.ajax
调用是POST
方法,并且我们将cache设置为false{cache:false}
,但这种情况仍在发生。我们尝试手动将timestamp
添加到标头,但没有帮助。
我们做了更多的研究,发现Safari只是为具有静态函数签名的web服务返回缓存的结果,并且在调用之间不会发生变化。例如,假设一个函数叫做:
getNewRecordID(intRecordType)
这个函数一遍又一遍地接收相同的输入参数,但是每次返回的数据应该都不一样。
想必是因为苹果急于让iOS6快速运行,他们对缓存设置太满意了。还有人在iOS 6上看到过这种行为吗?如果是的话,究竟是什么原因导致的呢?
我们找到的解决办法是将函数签名修改为如下所示:
getNewRecordID(intRecordType, strTimestamp)
然后始终传入timestamp
参数,并在服务器端丢弃该值。这是围绕着问题工作的。我希望这能帮助一些像我一样在这个问题上花费15个小时的其他可怜的灵魂!
经过一番调查,iOS6上的Safari会缓存没有Cache-Control头或者甚至“Cache-Control:max-age=0”的帖子。
我发现的防止这种缓存在全局级别发生的唯一方法,而不是必须在服务调用的末尾破解随机查询字符串,就是设置“cache-control:no-cache”。
所以:
我怀疑苹果公司正在利用HTTP规范中关于POST的9.5节中的这一点:
对此方法的响应不可缓存,除非响应包括适当的缓存控制或Expires标头字段。然而,303(参见其他)响应可用于指导用户代理检索可缓存资源。
所以理论上你可以缓存POST响应。。。谁知道呢。但直到现在,还没有其他浏览器制造商认为这会是个好主意。但这并不考虑在没有设置缓存控制或过期头时的缓存,只有在设置了一些缓存时才考虑缓存。所以肯定是虫子。
下面是我在Apache配置的正确部分中使用的以整个API为目标的内容,因为碰巧我实际上不想缓存任何东西,甚至连get都不想缓存。我不知道的是如何设置这个只是为了贴吧。
Header set Cache-Control "no-cache"
更新:只是注意到我没有指出,只有当帖子是相同的,所以改变任何一个帖子数据或URL,你就没事了。因此,正如在别处提到的,您可以向URL添加一些随机数据或一些POST数据。
更新:您可以将“no-cache”仅限于post,如果您希望在Apache中这样做的话:
SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST
我希望这能对其他在这个问题上碰壁的开发人员有所帮助。我发现以下任何一种情况都会阻止iOS6上的Safari缓存POST响应:
我的解决方案在我的Javascript中如下所示(我的所有AJAX请求都是POST的)。
$.ajaxSetup({
type: 'POST',
headers: { "cache-control": "no-cache" }
});
我还将[pragma:no-cache]头添加到许多服务器响应中。
如果您使用上述解决方案,请注意您所做的任何设置为global:false的$.ajax()调用都不会使用$.ajaxsetup()中指定的设置,因此您需要再次添加头。
所有web服务请求的简单解决方案,假设您正在使用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()
}));
});
请在此处阅读有关jQuery预筛选器调用的更多信息。
如果您没有使用jQuery,请检查文档中所选的库。它们可能具有类似的功能。