如何使Microsoft XmlHttpRequest荣誉缓存控制指令

Ian*_*oyd 30 msxml xmlhttprequest cache-control

我正在使用MSXML的XmlHttpRequest对象发出请求:

IXMLHttpRequest http = new XmlHttpRequest();
http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml", False, "", "");
http.send();
Run Code Online (Sandbox Code Playgroud)

并且send成功了,我得到了我的xml数据.

除了XmlHttpRequest实际上没有打网络(我可以看到没有发出实际的http请求).并且Process Monitor显示文件实际上是从我的缓存中提供的:

在此输入图像描述

所以我想指示XmlHttpRequest用户代理任何超过0秒的缓存内容都太旧了.执行此操作的标准方法是添加请求标头:

Cache-Control: max-age=0
Run Code Online (Sandbox Code Playgroud)

发送请求:

http = new XmlHttpRequest();
http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml", False, "", "");
http.setRequestHeader("Cache-Control", "max-age=0");
http.send();
Run Code Online (Sandbox Code Playgroud)

并且send成功了,我得到了我的xml数据.

除了XmlHttpRequest实际上没有打网络(我可以看到没有发出实际的http请求).Process Monitor显示文件实际上是从我的缓存中提供的.

那有什么不对?是max-age不是在做什么我想它呢?

来自RFC 2616 - 超文本传输​​协议,第14部分:标题字段定义:

其他指令允许用户代理修改基本过期机制.可以在请求中指定这些指令:

max-age
表示客户端愿意接受年龄不大于指定时间(秒)的响应.除非还包括最大指令,否则客户不愿意接受陈旧的响应.

这正是我想要的.

Cache-Control: max-age=0不是我想要的,或者是MSXML的XmlHttpRequest对象错误?

更新一

这是MSXML XmlHttpRequestCOM对象:

  • CLSID:{88d96a0a-f192-11d4-a65f-0040963251e5}
  • ProgID:Msxml2.XMLHTTP.6.0

更新二

max-age指令由客户端添加,以供所有要遵守的缓存使用.来自RFC:

Cache-Control通用头字段用于指定请求/响应链中的所有缓存机制必须遵守的指令 .指令指定旨在防止高速缓存对请求或响应产生负面干扰的行为.这些指令通常会覆盖默认的缓存算法.缓存指令是单向的,因为请求中存在指令并不意味着在响应中给出相同的指令.

Max-age不适用于服务器; 它对服务器没有意义.它适用于用户和服务器之间的所有缓存系统.

更新三

W3C XmlHttpRequest:

如果用户代理实现HTTP缓存,则它应该尊重 Cache-ControlsetRequestHeader()(例如, Cache-Control: no-cache绕过缓存)设置的请求头.除非最终用户明确请求此类行为(例如,通过重新加载页面),否则它不得自动发送Cache-ControlPragma请求标头.

按照他们的例子,我尝试使用该no-cache指令:

http = new XmlHttpRequest();
http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml", False, "", "");
http.setRequestHeader("Cache-Control", "no-cache");
http.send();
Run Code Online (Sandbox Code Playgroud)

并且XmlHttpRequest客户端仍然完全从缓存服务请求,而根本不查询服务器.

W3C说如果有一个缓存,它必须尊重Cache-Control它是否通过设置setRequestHeader.微软的XmlHttpRequest似乎并不尊重这一要求.

Gar*_*ett 17

不幸的是,XMLHttpRequest对象是这样设计的,因为它基于WinInet.此外,不建议从服务器端使用.你应该使用ServerXMLHttpRequest,具有相同的功能,但取决于WinHTTP相反.有关详细信息,请参阅常见问题 ServerXMLHttp文档中的描述指出:

HTTP客户端堆栈提供更长的正常运行时间.WinInet功能对服务器应用程序并不重要,例如URL缓存,代理服务器的自动发现,HTTP/1.1分块,离线支持以及对Gopher和FTP协议的支持不包含在新的HTTP子集中.

这意味着不是使用XmlHttpRequest:

IXMLHTTPRequest http = CreateComObject("Msxml2.XMLHTTP.6.0");     http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml", False, "", "");
http.setRequestHeader("Cache-Control", "max-age=0");
http.send();
Run Code Online (Sandbox Code Playgroud)

您可以使用ServerXmlHttpRequest:

IXMLHTTPRequest http = CreateComObject("Msxml2.ServerXMLHTTP");
http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml", False, "", "");
http.setRequestHeader("Cache-Control", "max-age=0");
http.send();
Run Code Online (Sandbox Code Playgroud)

WinHttpRequest:

IWinHttpRequest http = CreateComObject("WinHttp.WinHttpRequest.5.1");
http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml", False, "", "");
http.setRequestHeader("Cache-Control", "max-age=0");
http.send();
Run Code Online (Sandbox Code Playgroud)


小智 5

我发现使用If-None-Matchheader,指定一个ETag与上一个请求不匹配的值将起作用.

例如:

req.open("GET", url, false);
req.setRequestHeader("If-None-Match", "\"doesnt-match-anything\"");
req.send();
Run Code Online (Sandbox Code Playgroud)

这可能会或可能不会要求回复包括ETag.(我只尝试使用包含ETag每个响应中的值的服务.)