Как сделать директиву управления кешем 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, похоже, не соблюдает это требование.
Ответы
Ответ 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?