Подтвердить что ты не робот

Как сделать директиву управления кешем Microsoft XmlHttpRequest

Я выдаю запрос с использованием 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?

Обновить один

Это COM-объект MSXML XmlHttpRequest:

  • 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, похоже, не соблюдает это требование.

4b9b3361

Ответ 1

К сожалению, объект 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();

Ответ 2

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

Например:

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

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

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

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

Я не был знаком с заголовком, поэтому немного поработал над кешем-контролем: 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: частный? и http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

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

Ответ 7

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

Легкий трюк заключается в загрузке страницы следующим образом:

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

Ответ 8

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

http://youlink?mysession=random_number

Войтек

Ответ 9

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

Я согласен с тем, что это не идеальное решение, но не решение, но Mozilla на самом деле рекомендует это как обходной путь, поэтому я считаю, что это не должно быть слишком страшно - https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest

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

Ответ 10

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

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

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

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