Поведение кэширования 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 без изменений)
Ответы
Ответ 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 делает недопустимое поведение.