Поведение кэширования 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.

Обновите, вот заголовки ответа от coachdb (взятые из отладчика 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 Not Modified)


person NiklasN    schedule 09.12.2011    source источник
comment
Кэширование не является тривиальным. Можете ли вы обновить свой пост с заголовками запросов обоих вызовов?   -  person Asken    schedule 09.12.2011
comment
Я не думаю, что заголовки запросов в этом случае необходимы. Поскольку я смущен, почему HttpClient даже выполняет этот второй вызов (по сравнению с HttpWebRequest, который выполняет только один вызов).   -  person NiklasN    schedule 09.12.2011
comment
Обычно ТОЛЬКО заголовки имеют значение с точки зрения того, что сервер отправляет вам.   -  person Asken    schedule 09.12.2011
comment
О, вы имели в виду заголовки ответов? Я обновлю их..   -  person NiklasN    schedule 09.12.2011
comment
Каково значение заголовка must-revalidate, на который вы ссылаетесь?   -  person Rowland Shaw    schedule 09.12.2011
comment
Служба вернет то же самое, если запрос будет таким же. Поэтому взгляните на заголовки запроса в обоих случаях. Между ними должна быть разница.   -  person Asken    schedule 09.12.2011
comment
Аскен, проблема не в ответе. Дело в том, что с HttpWebRequest нет второго запроса. И я хотел бы, чтобы HttpClient вел себя так же. Только один раз спросить..   -  person NiklasN    schedule 09.12.2011
comment
Обновил вопрос с заголовками..   -  person NiklasN    schedule 09.12.2011


Ответы (2)


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

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

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

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

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

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

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

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

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

person Hans Malherbe    schedule 10.02.2012
comment
Спасибо за правильный ответ. Я принял это. Это многое прояснило для меня! - person NiklasN; 29.09.2012

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

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

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

person NiklasN    schedule 12.12.2011
comment
Это неправильно, в спецификации об этом не сказано. Правильный ответ дан Гансом Малхербом - person Pavel Gatilov; 28.09.2012