System.Net.Http.HttpClient Кэширование поведения - PullRequest
15 голосов
/ 09 декабря 2011

Я использую HttpClient 0.6.0 от NuGet.

У меня есть следующий код C #:

var client = new HttpClient(new WebRequestHandler() {
    CachePolicy =
        new HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable)
});
client.GetAsync("http://myservice/asdf");

Служба (на этот раз CouchDB) возвращает значение ETag и код состояния 200 OK. Возвращается заголовок Cache-Control со значением must-revalidate

Обновление, вот заголовки ответа от couchdb (взяты из отладчика visual studio):

Server: CouchDB/1.1.1 (Erlang OTP/R14B04)
Etag: "1-27964df653cea4316d0acbab10fd9c04"
Date: Fri, 09 Dec 2011 11:56:07 GMT
Cache-Control: must-revalidate

В следующий раз, когда я сделаю точно такой же запрос, HttpClient выполнит условный запрос и вернется 304 Not Modified. Что верно.

Однако, если я использую низкоуровневый класс HttpWebRequest с тем же CachePolicy, запрос даже не выполняется во второй раз. Именно так я бы хотел, чтобы HttpClient также вел себя.

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

(Кроме того, в качестве сопутствующего примечания при отладке код состояния ответа отображается как 200 OK, даже если служба возвращает значение 304 Не изменено)

Ответы [ 2 ]

24 голосов
/ 10 февраля 2012

Оба клиента ведут себя правильно.

must-revalidate применяется только к устаревшим ответам .

Когда директива must-revalidate присутствует в ответе, полученномcache, этот кеш НЕ ДОЛЖЕН использовать запись после того, как она устареет , чтобы ответить на последующий запрос, не проверив его сначала на исходном сервере.(То есть, кэш ДОЛЖЕН выполнять сквозную повторную проверку каждый раз, , если , основываясь исключительно на значении Expires или max-age исходного сервера, кэшированный ответ устарел .)

Так как вы не предоставляете явное истечение срока действия, кешам разрешено использовать эвристику для определения свежести .

, так как вы не предоставляете Last-Modified кеша не нужно предупреждать клиента об использовании эвристики.

Если ни одно из значений Expires, Cache-Control: max-age или Cache-Control: s-maxage (см. Раздел14.9.3) появляется в ответе, и ответ не включает другие ограничения на кеширование, кеш МОЖЕТ вычислить время жизни свежести с использованием эвристики .Кэш ДОЛЖЕН прикреплять Предупреждение 113 к любому ответу , возраст которого превышает 24 часа , если такое предупреждение еще не было добавлено.

Ответ возраст рассчитывается на основеDate заголовок , поскольку Age отсутствует.

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

Одно из объяснений состоит в том, что HttpWebRequest использует эвристику и что был сохраненный ответ с кодом состояния 200, который все еще был свежим.

0 голосов
/ 12 декабря 2011

Отвечая на мой вопрос ..

Согласно http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4 Я бы сказал, что «Cache-Control: must-revalidate» без истечения срока действия указывает, что ресурс должен проверяться при каждом запросе.

В этом случае это означает, что условное GET должно выполняться каждый раз, когда создается ресурс. Таким образом, в этом случае System.Net.Http.HttpClient работает правильно, а устаревший (Http) WebRequest выполняет некорректное поведение.

...