自升级到 iOS 6 以来,我们看到 Safari 的 Web 视图可以自由缓存$.ajax
调用。这是在 PhoneGap 应用程序的上下文中,因此它使用 Safari WebView。我们的$.ajax
调用是POST
方法,我们将缓存设置为 false {cache:false}
,但仍然会发生这种情况。我们尝试手动向标头添加TimeStamp
但它没有帮助。
我们做了更多研究,发现 Safari 只返回具有静态功能签名并且不会因呼叫而改变的 Web 服务的缓存结果。例如,想象一个名为:
getNewRecordID(intRecordType)
该函数反复接收相同的输入参数,但每次返回的数据应该不同。
一定是苹果急于让 iOS 6 拉链令人印象深刻,他们对缓存设置感到满意。还有其他人在 iOS 6 上看到过这种行为吗?如果是这样,究竟是什么导致了它?
我们发现的解决方法是将函数签名修改为如下所示:
getNewRecordID(intRecordType, strTimestamp)
然后总是传入一个TimeStamp
参数,并在服务器端丢弃该值。这解决了这个问题。我希望这能帮助其他一些在这个问题上花费 15 个小时的穷人,就像我一样!
经过一番调查后,发现 iOS6 上的 Safari 将缓存没有 Cache-Control 标头甚至 “Cache-Control:max-age = 0” 的 POST。
我发现阻止此缓存在全局级别发生的唯一方法是设置 “Cache-Control:no-cache”,而不是将随机查询字符串发送到服务调用结束。
所以:
我怀疑 Apple 在第 9.5 节关于 POST 的 HTTP 规范中利用了这一点:
除非响应包含适当的 Cache-Control 或 Expires 头字段,否则对此方法的响应不可缓存。但是,303(请参阅其他)响应可用于指示用户代理检索可缓存资源。
所以理论上你可以缓存 POST 响应...... 谁知道。但直到现在还没有其他浏览器制造商认为这是一个好主意。但是,如果没有设置 Cache-Control 或 Expires 标头,那么这不会考虑缓存,只有在有一些设置时才会考虑。所以一定是个 bug。
下面是我在我的 Apache 配置的正确位置使用的目标我的整个 API,因为它实际上我实际上并不想缓存任何东西,甚至得到。我不知道的是如何为 POST 设置它。
Header set Cache-Control "no-cache"
更新:刚刚注意到我没有指出它只是在 POST 是相同的时候,所以更改任何 POST 数据或 URL,你就没事了。所以你可以像其他地方一样在网址或一些 POST 数据中添加一些随机数据。
更新:如果你想在 Apache 中这样做,你可以将 “无缓存” 限制为 POST:
SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST
我希望这可以对其他开发人员在这个问题上猛烈抨击。我发现以下任何一种情况都会阻止 iOS 6 上的 Safari 缓存 POST 响应:
我的解决方案是我的 Javascript 中的以下内容(我的所有 AJAX 请求都是 POST)。
$.ajaxSetup({
type: 'POST',
headers: { "cache-control": "no-cache" }
});
我还将 [pragma:no-cache] 标头添加到我的许多服务器响应中。
如果你使用上面的解决方案,请注意任何 $ .ajax()调用你设置为 global:false 将不使用 $ .ajaxSetup()中指定的设置,因此你需要再次添加标题。
假设您正在使用 jQuery,所有 Web 服务请求的简单解决方案:
$.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 prefilter 调用的更多信息。
如果您不使用 jQuery,请检查您选择的库的文档。它们可能具有类似的功能。