Почему HttpCacheability.Private подавляет ETag? - PullRequest
25 голосов
/ 28 августа 2008

При написании пользовательского IHttpHandler я столкнулся с поведением, которое я не ожидал в отношении объекта HttpCachePolicy.

Мой обработчик вычисляет и устанавливает тег сущности (используя метод SetETag для HttpCachePolicy, связанный с текущим объектом ответа). Если я устанавливаю открытый элемент управления кэшированием, используя метод SetCacheability, все работает как чудо, и сервер отправляет заголовок электронного тега. Если я установлю это как приватное, заголовок электронного тега будет подавлен.

Может быть, я просто не выглядел достаточно усердно, но я не видел в спецификации HTTP / 1.1 ничего, что могло бы оправдать такое поведение. Почему вы не хотите отправлять E-Tag в браузеры, в то же время запрещая прокси хранить данные?

using System;
using System.Web;

public class Handler : IHttpHandler {
    public void ProcessRequest (HttpContext ctx) {
        ctx.Response.Cache.SetCacheability(HttpCacheability.Private);
        ctx.Response.Cache.SetETag("\"static\"");
        ctx.Response.ContentType = "text/plain";
        ctx.Response.Write("Hello World");
    }

    public bool IsReusable { get { return true; } }
}

Вернется

Cache-Control: private
Content-Type: text/plain; charset=utf-8
Content-Length: 11

Но если мы изменим его на public, он вернется

Cache-Control: public
Content-Type: text/plain; charset=utf-8
Content-Length: 11
Etag: "static"

Я запустил это на сервере разработки ASP.NET и IIS6 до сих пор с одинаковыми результатами. Также я не могу явно установить ETag, используя

Response.AppendHeader("ETag", "static")

Обновление : возможно добавить заголовок ETag вручную при работе в IIS7, я подозреваю, что это вызвано тесной интеграцией между ASP.NET и конвейером IIS7.

Разъяснение : Это длинный вопрос, но основной вопрос заключается в следующем: Почему ASP.NET делает это, как я могу обойти это и должен ли я?

Обновление : Я собираюсь принять Ответ Тони , поскольку он по сути правильный (иди к Тони!). Я обнаружил, что если вы хотите полностью эмулировать HttpCacheability.Private, вы можете установить кеширование на ServerAndPrivate, но у вас также есть кеш вызовов. SetOmitVaryStar (true), иначе кэш добавит Vary: * заголовок к выводу, и вы не хотите этого. Я отредактирую это в ответ, когда получу разрешения на редактирование (или, если вы видите Тони, возможно, вы могли бы отредактировать свой ответ, чтобы включить этот вызов?)

Ответы [ 3 ]

17 голосов
/ 29 августа 2008

Я думаю, вам нужно использовать HttpCacheability.ServerAndPrivate

Это должно дать вам контроль кэша: private в заголовках и позволит вам установить ETag.

Документация по этому вопросу должна быть немного лучше.

Редактировать: Маркус обнаружил, что у вас также есть кеш вызовов. SetOmitVaryStar (true) в противном случае кеш добавит заголовок Vary: * к выводу, и вы этого не захотите.

3 голосов
/ 29 августа 2008

К сожалению, если вы посмотрите на System.Web.HttpCachePolicy.UpdateCachedHeaders() в .NET Reflector, вы увидите, что есть оператор if, специально проверяющий, что Cacheability не является Private перед выполнением каких-либо операций ETag. В любом случае, я всегда обнаруживал, что Last-Modified/If-Modified-Since хорошо работает с нашими данными и в любом случае немного проще контролировать в Fiddler.

0 голосов
/ 30 марта 2012

Если, как и я, вы недовольны упомянутым здесь обходным приемом использования Cacheability.ServerAndPrivate, и вы действительно хотите использовать вместо него Private - возможно, потому что вы настраиваете страницы индивидуально для пользователей, и нет смысла кэшировать на сервере - тогда, по крайней мере, в .NET 3.5 вы можете установить ETag через Response.Headers.Add, и это прекрасно работает.

N.B. если вы сделаете это, вы должны будете сами сравнить заголовки клиента и обработку ответов HTTP 304 - не уверены, что .NET позаботится об этом за вас при нормальных обстоятельствах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...