如何使 Microsoft XmlHttpRequest 尊重缓存控制指令 [英] How to make Microsoft XmlHttpRequest honor cache control directive

查看:11
本文介绍了如何使 Microsoft XmlHttpRequest 尊重缓存控制指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 MSXML 的 是添加请求头:p>

缓存控制:max-age=0

发送请求:

http = new XmlHttpRequest();http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml", False, "", "");http.setRequestHeader("缓存控制", "max-age=0");http.send();

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

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

那么有什么问题吗?max-age 没有像我认为的那样做吗?

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

<块引用>

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

最大年龄
表示客户端是愿意接受年龄不大于指定时间马上.除非 max-stale指令也包括在内,客户端不愿接受陈旧回应.

这正是我想要的.

Cache-Control: max-age=0 不是我想要的,还是 MSXML 的 XmlHttpRequest 对象有问题?

更新一

这是 MSXML XmlHttpRequest COM 对象:

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

更新二

max-age 指令由客户端添加,以便所有缓存都遵守.来自 RFC:

<块引用>

Cache-Control 通用标头字段用于指定指令所有缓存都必须遵守请求/响应机制链.指令指定行为旨在防止缓存不利地干扰请求或回应.这些指令通常会覆盖默认缓存算法.缓存指令是单向的,因为存在请求中的指令不暗示同样的指令是在响应中给出.

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

更新三

来自 W3C XmlHttpRequest:

<块引用>

如果用户代理实现了 HTTP 缓存,它应该尊重Cache-Control 请求头设置setRequestHeader()(例如,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("缓存控制", "无缓存");http.send();

XmlHttpRequest 客户端仍然完全从缓存中处理请求,根本不查询服务器.

W3C 说如果有缓存,如果通过setRequestHeader 设置,它必须遵守Cache-Control.Microsoft 的 XmlHttpRequest 似乎没有满足这一要求.

解决方案

不幸的是 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("缓存控制", "max-age=0");http.send();

您可以使用 ServerXmlHttpRequest:

IXMLHTTPRequest http = CreateComObject("Msxml2.ServerXMLHTTP");http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml", False, "", "");http.setRequestHeader("缓存控制", "max-age=0");http.send();

WinHttpRequest:

IWinHttpRequest http = CreateComObject("WinHttp.WinHttpRequest.5.1");http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml", False, "", "");http.setRequestHeader("缓存控制", "max-age=0");http.send();

i'm issuing a request using MSXML's XmlHttpRequest object:

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

And the send succeeds, and i get my xml data.

Except that XmlHttpRequest didn't actually hit the network (i can see there no actual http request issued). And Process Monitor shows the file is actually being served from my cache:

So i want to instruct the XmlHttpRequest user agent that any cached content older than 0 seconds is too old. The standards way to do this is to add a request header:

Cache-Control: max-age=0

to the send request:

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

And the send succeeds, and i get my xml data.

Except that XmlHttpRequest didn't actually hit the network (i can see there no actual http request issued). And Process Monitor shows the file is actually being served from my cache.

So what is wrong? Is max-age not doing what i think it does?

From RFC 2616 - Hypertext Transfer Protocol, Part 14: Header Field Definitions:

Other directives allow a user agent to modify the basic expiration mechanism. These directives MAY be specified on a request:

max-age
Indicates that the client is willing to accept a response whose age is no greater than the specified time in seconds. Unless max- stale directive is also included, the client is not willing to accept a stale response.

Which exactly what i want.

Is Cache-Control: max-age=0 not exactly what i want, or is MSXML's XmlHttpRequest object buggy?

Update One

This is the MSXML XmlHttpRequest COM object:

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

Update Two

The max-age directive is added by the client for all cache's to adhere to. From RFC:

The Cache-Control general-header field is used to specify directives that MUST be obeyed by all caching mechanisms along the request/response chain. The directives specify behavior intended to prevent caches from adversely interfering with the request or response. These directives typically override the default caching algorithms. Cache directives are unidirectional in that the presence of a directive in a request does not imply that the same directive is to be given in the response.

Max-age is not for the server; it makes no sense for a server. It is intended for all caching systems between the user and the server.

Update Three

From W3C XmlHttpRequest:

If the user agent implements a HTTP cache it should respect Cache-Control request headers set by the setRequestHeader() (e.g., Cache-Control: no-cache bypasses the cache). It must not send Cache-Control or Pragma request headers automatically unless the end user explicitly requests such behavior (e.g. by reloading the page).

Following their example, i tried using the no-cache directive:

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

And the XmlHttpRequest client still services requests completely from the cache, without querying the server at all.

The W3C says that if there is a cache, it must honor Cache-Control if it is set through setRequestHeader. Microsoft's XmlHttpRequest doesn't seem to honor that requirement.

解决方案

Unfortunately the XMLHttpRequest object was designed this way, because it is based on WinInet. Also, it is not recommend to be used from the server side. You should use ServerXMLHttpRequest, which has the same functionality, but depends on WinHTTP instead. See the FAQ for more information. A description from the ServerXMLHttp documentation states that:

The HTTP client stack offers longer uptimes. WinInet features that are not critical for server applications, such as URL caching, auto-discovery of proxy servers, HTTP/1.1 chunking, offline support, and support for Gopher and FTP protocols are not included in the new HTTP subset.

This means that rather than using 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();

you can use 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();

or 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();

这篇关于如何使 Microsoft XmlHttpRequest 尊重缓存控制指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆