iOS 6 上的 Safari 是否缓存 $.ajax 结果?

自从升级到iOS 6以来,我们看到Safari的Web视图可以自由缓存调用。这是在PhoneGap应用程序的上下文中,因此它使用的是Safari WebView。我们的调用是方法,我们将缓存设置为 false ,但这仍然在发生。我们尝试手动将 a 添加到标头中,但没有帮助。$.ajax$.ajaxPOST{cache:false}TimeStamp

我们做了更多的研究,发现 Safari 只返回 Web 服务的缓存结果,这些服务的函数签名是静态的,不会因调用而变化。例如,想象一个名为以下内容的函数:

getNewRecordID(intRecordType)

此函数一遍又一遍地接收相同的输入参数,但它每次返回的数据都应该不同。

必须以Apple的速度使iOS 6压缩令人印象深刻,他们对缓存设置非常满意。有没有人在iOS 6上看到过这种行为?如果是这样,究竟是什么原因造成的?


我们发现的解决方法是将函数签名修改为如下所示:

getNewRecordID(intRecordType, strTimestamp)

然后始终传入参数,并在服务器端丢弃该值。这可以解决此问题。TimeStamp


答案 1

经过一番调查,事实证明,iOS6上的Safari将缓存没有Cache-Control标头甚至“Cache-Control:max-age=0”的POST。

我发现防止这种缓存在全局级别发生而不是必须将随机查询字符串破解到服务调用结束的唯一方法是设置“缓存控制:无缓存”。

所以:

  • 无缓存控制或过期标头 = iOS6 Safari 将缓存
  • 缓存控制最大年龄 = 0,并且立即过期 = iOS6 Safari 将缓存
  • 缓存控制:无缓存 = iOS6 Safari 不会缓存

我怀疑Apple正在利用有关POST的第9.5节中的HTTP规范中的这一点:

对此方法的响应不可缓存,除非响应包含相应的“缓存控制”或“过期”标头字段。但是,303(请参阅其他)响应可用于指示用户代理检索可缓存资源。

因此,从理论上讲,您可以缓存POST响应...谁知道呢。但到目前为止,还没有其他浏览器制造商认为这将是一个好主意。但是,当没有设置缓存控制或 Expires 标头时,这并不能考虑缓存,只有当有一些设置时。所以它一定是一个错误。

以下是我在Apache配置的正确部分中使用的内容,以针对我的整个API,因为碰巧我实际上并不想缓存任何内容,甚至不需要获取。我不知道的是,如何仅为POST设置它。

Header set Cache-Control "no-cache"

更新:只是注意到我没有指出只有当POST相同时,所以更改任何POST数据或URL,你就可以了。因此,您可以像其他地方提到的那样,只需向URL添加一些随机数据或一些POST数据即可。

更新:如果您愿意在Apache中这样做,您可以将“无缓存”限制为POST:

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

答案 2

我希望这能对其他开发人员有用,他们把头撞在墙上。我发现以下任何一项都会阻止iOS 6上的Safari缓存POST响应:

  • 在请求标头中添加 [缓存控制:无缓存]
  • 添加变量 URL 参数,如当前时间
  • 在响应标头中添加 [编译指示:无缓存]
  • 在响应标头中添加 [缓存控制:无缓存]

我的解决方案是在我的Javascript中如下(我所有的AJAX请求都是POST)。

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

我还将 [pragma: no-cache] 标头添加到我的许多服务器响应中。

如果您使用上述解决方案,请注意,您所做的任何设置为 global: false 的 $.ajax() 调用都不会使用 $.ajaxSetup() 中指定的设置,因此您需要再次添加标头。