How to make Microsoft XmlHttpRequest honor cache control directive

混江龙づ霸主 提交于 2019-11-28 07:15:41
Garett

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();
J. Mullaney

I found that using If-None-Match header, specifing a value that does not match the ETag of the last request will work.

Eg:

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

This might or might not require that the responses include an ETag. (I only tried it with a service that includes an ETag value in each response.)

Could you append a bogus parameter on the end of your URI that changes with each request?

http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml?requestID=42", False, "", "");
tranzitwww

I use this for a keep-alive session and it works great.
The trick is to use the header "If-Modified-Since" with a value newer that the one cached by the browser.

g_AjaxObj.onreadystatechange = function() { if(g_AjaxObj.readyState === 4) { AjaxOnComplete_("KeepAlive"); }};
g_AjaxObj.open('GET', URL, true);
g_AjaxObj.setRequestHeader("If-Modified-Since", new Date().toUTCString());
g_AjaxObj.send(null);

My quick and dirty workaround at a standard Windows client was
- Internet Options
- General
- Browsing history Settings
- Check for newer Versions of stored pages:
tickle "(x) Every time I visit the Webpage"
Now my Msxml2.XMLHTTP.x.0 Object don't use the Cache anymore ...

This header is for the server, and as the browser doesnt event do any request, its useless.

An easy trick is to load the page like this :

http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml?"+Math.random(), False, "", "");

For old msxml library, I use random generated value for uri adress eg :

http://youlink?mysession=random_number

wojtek

Downside of that is that you flood the cache with multiple copies of the same content. It might be a hack around buggy http agents - but a real solution is to work with caching mechanisms, rather than against them. –

I agree that this is not ideal and not really a solution, but Mozilla actually recommend this as a workaround, so I figure it mustn't be too terrible - https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest

Besides, I was tearing my hair out trying to solve this. I've had to rely on my users to clear their browser (which they keep forgetting to do). So this is a godsend for me!

Matt

Try sending 'cache-control: private' as a header. This worked for me:

var request = new XMLHttpRequest();
request.open("GET", 'http://myurl.com' , false); 

request.setRequestHeader("cache-control", "private");

I'm writing a HTML & Javascript app for Windows 8 where and both no-cache and max-age are ignored. For me the above works just fine.

I wasn't familiar with the header so did a little digging on cache-control: private...

Indicates that all or part of the response message is intended for a single user and MUST NOT be cached by a shared cache, such as a proxy server.

From What is Cache-Control: private? and http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

So, basically, this will never create a cache entry and therefore doesn't add cache entries that we know are superfluous, as with a 'cache-buster' random number parameter.

MarkCheshire

This was driving me crazy. This SO thread came closest to providing an answer. Unfortunately during testing none of them actually worked for me. The only solution I found which tested to work correctly was setting:

Header Pragma: no-cache

I hope it saves others with IE headaches.

BTW this is StackOverflow thread is great to shed light on the difference between Pragma and Cache-control: Difference between Pragma and Cache-control headers?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!