我正在使用nginx和Dojo构建一个由一组JSON文件驱动的嵌入式UI。我们的主要目标浏览器是Chrome,但它应该可以与所有现代浏览器配合使用。
更改JSON文件可以极大地改变UI,我用它向不同的用户提供不同的演示。有关详细信息,请参阅我之前的问题(配置nginx将不同的文件返回给具有相同URI的不同身份验证用户),但基本上,我的nginx配置是这样的,即不同用户的相同URI可以产生不同的内容。
这一切都很好,除非有人切换到另一个用户。有些浏览器会从自己的内部缓存中获取这些JSON文件,甚至不需要与服务器进行检查,这会使UI显示以前用户的演示。重新加载页面可以修复它,但天哪!我宁愿正确的事情自动发生。
显而易见的解决方案是使用各种缓存头,但它们似乎没有帮助。我使用以下nginx指令:
expires epoch;
etag off;
if_modified_since off;
add_header Last-Modified "";
其产生以下响应标头:
HTTP/1.1 200 OK
Server: nginx/1.4.1
Date: Wed, 24 Sep 2014 16:58:32 GMT
Content-Type: application/octet-stream
Content-Length: 1116
Connection: keep-alive
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Cache-Control: no-cache
Accept-Ranges: bytes
对我来说,这看起来很有说服力,但问题仍然存在于Chrome 36 for OS X和Opera 24 for OS X(尽管Firefox 29和32做了正确的事情)。Chrome满足于从缓存中抓取文件,甚至不需要参考服务器。
下面是一个详细的例子,标题是从Chrome的网络调试面板中提取的。Chrome第一次获取/app/resources/states.json时,Chrome报告
Remote Address:75.144.159.89:8765
Request URL:http://XXXXXXXXXXXXXXX/app/resources/screens.json
Request Method:GET
Status Code:200 OK
带有请求标头:
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Authorization:Basic dm9sdGFpcndlYjp2b2x0YWly
Cache-Control:max-age=0
Connection:keep-alive
Content-Type:application/x-www-form-urlencoded
DNT:1
Host:suitable.dyndns.org:8765
Referer:http://XXXXXXXXXXXXXXXXXXXXXX/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
X-Requested-With:XMLHttpRequest
和响应标头:
Accept-Ranges:bytes
Cache-Control:no-cache
Connection:keep-alive
Content-Length:2369
Content-Type:application/octet-stream
Date:Wed, 24 Sep 2014 17:19:46 GMT
Expires:Thu, 01 Jan 1970 00:00:01 GMT
Server:nginx/1.4.1
再说一遍,一切都很好。但是,当我更改用户时(通过重新启动Chrome,然后重新加载父页面),我会得到以下Chrome报告:
Remote Address:75.144.159.89:8765
Request URL:http://suitable.dyndns.org:8765/app/resources/states.json
Request Method:GET
Status Code:200 OK (from cache)
与服务器没有明显的联系。
似乎并非所有文件都会出现这种情况。一些.js文件被缓存,大多数没有;css文件似乎都没有缓存;缓存所有.html文件,缓存所有.json文件。
我怎么能告诉浏览器(我看着你,Chrome!)这些文件在它请求它们的那一刻很好,但永远不会好起来?这是Chrome漏洞吗?(如果是这样的话,Opera也显示了这个问题,这很奇怪。)
我相信我已经发现了问题。显然,"缓存控制:没有缓存"不足以告诉浏览器,嗯,不要缓存数据。我添加了"无店铺":
Cache-Control:no-store, no-cache
这就成功了。不再使用Chrome或Opera缓存。
我遇到了同样的问题,json被缓存。。。
如果控制客户端应用程序代码,一个可能的解决方法是在URL的末尾添加一个随机值查询参数。
因此,与其呼叫:
http://XXXXXXXXXXXXXXX/app/resources/screens.json
例如:
http://XXXXXXXXXXXXXXX/app/resources/screens.json?rand=rrrrrrrrrr
其中CCD_ 1是在每个呼叫中不同的一些随机值。
然后,浏览器将无法重用任何缓存的值。