Как заставить Microsoft XmlHttpRequest соблюдать директиву управления кэшем - PullRequest
29 голосов
/ 08 марта 2011

Я отправляю запрос, используя MSXML XmlHttpRequest объект:

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

И send успешно, и я получаю свои данные XML.

За исключением того, что XmlHttpRequest на самом деле не попал в сеть (я вижу, что фактический http-запрос не выдается). И Process Monitor показывает, что файл фактически обслуживается из моего кэша:

enter image description here

Итак, я хочу проинструктировать пользовательский агент XmlHttpRequest, что любое кэшированное содержимое старше 0 секунд слишком старое. стандартный способ сделать это - добавить заголовок запроса:

Cache-Control: max-age=0

на запрос на отправку:

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

И send успешно, и я получаю свои данные XML.

За исключением того, что XmlHttpRequest на самом деле не попал в сеть (я вижу, что фактический http-запрос не выдается). И Process Monitor показывает, что файл фактически обслуживается из моего кэша.

Так что не так? max-age не делает то, что мне кажется?

С RFC 2616 - Протокол передачи гипертекста, часть 14: Определения полей заголовка :

Другие директивы позволяют пользовательскому агенту изменить базовый механизм истечения. Эти директивы МОГУТ быть указаны на запрос:

Макс-возраст
Указывает, что клиент готовы принять ответ, чей возраст не больше указанного времени в секундах Если не максимально директива также включена, клиент не желает принимать несвежую ответ.

Что именно то, что я хочу.

Является ли 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 используется для указания директив, которые ДОЛЖНЫ быть подчинены всему кешированию механизмы вдоль запроса / ответа цепь . Директивы определяют поведение предназначен для предотвращения кэши от неблагоприятно вмешиваясь в запрос или ответ. Эти директивы обычно переопределяет кэширование по умолчанию алгоритмы. Директивы кэша однонаправленный в том, что наличие директива в запросе не подразумевают, что та же самая директива должна быть дано в ответе.

Макс-возраст не для сервера; это не имеет смысла для сервера. Он предназначен для всех систем кэширования между пользователем и сервером.

Обновление три

С W3C XmlHttpRequest :

Если пользовательский агент реализует кеш HTTP, он должен уважать Cache-Control заголовки запроса, установленные setRequestHeader() (например, Cache-Control: no-cache обходит кэш). Это не должно отправить Cache-Control или Pragma заголовки запроса автоматически, если конечный пользователь явно запрашивает такое поведение (например, перезагрузив страницу).

Следуя их примеру , я попытался использовать директиву 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();

А XmlHttpRequest клиент по-прежнему полностью обслуживает запросы из кэша, вообще не запрашивая сервер.

W3C говорит, что если есть кеш, он должен соблюдать Cache-Control, если он установлен через setRequestHeader. Microsoft XmlHttpRequest, похоже, не выполняет это требование.

Ответы [ 10 ]

16 голосов
/ 22 марта 2011

К сожалению, объект XMLHttpRequest был спроектирован таким образом, потому что он основан на WinInet. Кроме того, не рекомендуется использовать со стороны сервера. Вы должны использовать ServerXMLHttpRequest, который имеет те же функции, но зависит от WinHTTP. См. FAQ для получения дополнительной информации. Описание из документации ServerXMLHttp гласит:

Стек HTTP-клиента предлагает больше uptimes. Функции WinInet, которые не являются критично для серверных приложений, таких как в качестве URL-кэширования, авто-обнаружение прокси-серверы, HTTP / 1.1 chunking, автономная поддержка и поддержка Протоколы 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();

вы можете использовать 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();

или 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();
5 голосов
/ 06 января 2012

Я обнаружил, что с помощью заголовка If-None-Match указание значения, которое не соответствует ETag последнего запроса, будет работать.

Например:

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

Это может потребовать или не потребовать, чтобы ответы включали ETag. (Я пробовал это только с сервисом, который включает значение ETag в каждом ответе.)

1 голос
/ 16 июня 2014

Попробуйте отправить 'cache-control: private' в качестве заголовка. Это сработало для меня:

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

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

Я пишу приложение HTML & Javascript для Windows 8, в котором игнорируются как no-cache, так и max-age. Для меня вышесказанное работает просто отлично.

Я не был знаком с заголовком, поэтому немного покопался в управлении кэшем: 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.

С Что такое Cache-Control: private? и http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

Таким образом, в принципе, это никогда не создаст запись в кеше и, следовательно, не добавит записи в кеш, которые, как мы знаем, являются излишними, как в случае с параметром случайного числа 'cache-buster'.

1 голос
/ 07 мая 2014

Мой быстрый и грязный обходной путь на стандартном клиенте Windows был
- Свойства обозревателя
- Общие
- История просмотра Настройки
- Проверить наличиеболее новые версии сохраненных страниц:
tickle"(x) Каждый раз, когда я захожу на веб-страницу"
Теперь мой Msxml2.XMLHTTP.x.0 Объект не используетсяКеш больше ...

1 голос
/ 07 ноября 2011

Я использую это для поддержания активности, и это прекрасно работает.
Хитрость заключается в том, чтобы использовать заголовок «If-Modified-Since» с более новым значением, чем кэшированное браузером.

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);
1 голос
/ 08 марта 2011

Не могли бы вы добавить фиктивный параметр в конце вашего URI, который меняется с каждым запросом?

http.open("GET", "http://www.bankofcanada.ca/stat/fx-xml.xml?requestID=42", False, "", "");
0 голосов
/ 04 марта 2016

Это сводило меня с ума.Эта тема была ближе всего к ответу.К сожалению, во время тестирования никто из них на самом деле не работал для меня.Единственное решение, которое я нашел и которое протестировало для корректной работы, это настройка:

Заголовок Pragma: no-cache

Надеюсь, это спасет других от головной боли IE.

Кстати, это StackOverflowПоток замечательно, чтобы пролить свет на разницу между Pragma и Cache-control: Разница между Pragma и Cache-control??

0 голосов
/ 11 марта 2013

Недостатком является то, что вы заполняете кэш несколькими копиями одного и того же содержимого.Это может быть хаком с ошибочными агентами http - но реальное решение - работать с механизмами кэширования, а не против них.-

Я согласен, что это не идеально и не совсем решение, но Mozilla на самом деле рекомендует это как обходной путь, поэтому я считаю, что это не должно быть слишком ужасно1007 * Кроме того, я рвал на себе волосы, пытаясь решить эту проблему.Я должен был положиться на своих пользователей, чтобы очистить их браузер (что они постоянно забывают делать).Так что это находка для меня!

0 голосов
/ 19 сентября 2011

Для старой библиотеки msxml я использую случайное сгенерированное значение для адреса uri, например:

http://youlink? Mysession = random_number

wojtek

0 голосов
/ 08 марта 2011

Этот заголовок предназначен для сервера, и, поскольку браузер не выполняет никаких запросов, он бесполезен.

Простой трюк - загрузить страницу следующим образом:

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