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

Почему HttpCacheability.Private подавляет ETags?

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

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

Возможно, я просто не выглядел достаточно сложно, но я ничего не видел в спецификации 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

Но если мы изменим его на публичный, он вернет

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: * к выходу, и вы этого не хотите. Я отредактирую это в ответ, когда получаю разрешения на редактирование (или, если вы видите, что это Тони, возможно, вы можете отредактировать свой ответ, чтобы включить этот вызов?)

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

Ответ 3

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

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