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

Поведение кэширования System.Net.Http.HttpClient

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

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

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 (взяты из отладчика визуальной студии):

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 тоже вел себя.

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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