Pergunta

Ao escrever um IHttpHandler personalizado, me deparei com um comportamento que não esperava em relação ao objeto HttpCachePolicy.

Meu manipulador calcula e define uma tag de entidade (usando o método SetETag no HttpCachePolicy associado ao objeto de resposta atual).Se eu definir o controle de cache como público usando o método SetCacheability, tudo funcionará perfeitamente e o servidor enviará o cabeçalho da e-tag.Se eu definir como privado, o cabeçalho da e-tag será suprimido.

Talvez eu simplesmente não tenha procurado o suficiente, mas não vi nada na especificação HTTP/1.1 que justificasse esse comportamento.Por que você não gostaria de enviar E-Tag para navegadores e ao mesmo tempo proibir os proxies de armazenar os dados?

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; } }
}

Retornará

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

Mas se mudarmos para público, ele retornará

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

Eu executei isso no servidor de desenvolvimento ASP.NET e no IIS6 até agora com os mesmos resultados.Além disso, não consigo definir explicitamente o ETag usando

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

Atualizar:É possível anexar o cabeçalho ETag manualmente ao executar no IIS7. Suspeito que isso seja causado pela forte integração entre o ASP.NET e o pipeline do IIS7.

Esclarecimento:É uma pergunta longa, mas a questão central é esta: por que o ASP.NET faz isso, como posso contornar isso e devo?

Atualizar:eu vou aceitar A resposta de Tony já que está essencialmente correto (vai Tony!).Descobri que se você quiser emular totalmente o HttpCacheability.Private, poderá definir a capacidade de cache como ServerAndPrivate, mas também terá cache de chamadas.DefinirOmitVaryStar(verdadeiro), caso contrário o cache adicionará o Variar:* cabeçalho para a saída e você não quer isso.Editarei isso na resposta quando obtiver permissões de edição (ou se você vir este Tony, talvez possa editar sua resposta para incluir essa chamada?)

Foi útil?

Solução

Acho que você precisa usar HttpCacheability.ServerAndPrivate

Isso deve lhe dar controle de cache:private nos cabeçalhos e permite definir uma ETag.

A documentação sobre isso precisa ser um pouco melhor.

Editar: Markus descobriu que você também tem uma chamada cache.SetOmitVaryStar(true) caso contrário, o cache adicionará o Vary:* cabeçalho para a saída e você não quer isso.

Outras dicas

Infelizmente se você olhar System.Web.HttpCachePolicy.UpdateCachedHeaders() no .NET Reflector, você vê que há uma instrução if verificando especificamente se a capacidade de cache não é privada antes de fazer qualquer coisa de ETag.De qualquer forma, sempre achei isso Last-Modified/If-Modified-Since funciona bem para nossos dados e é um pouco mais fácil de monitorar no Fiddler.

Se, como eu, você não estiver satisfeito com a solução alternativa mencionada aqui de usar Cacheability.ServerAndPrivate e realmente quiser usar Private - talvez porque esteja personalizando páginas individualmente para usuários e não faz sentido armazenar em cache no servidor - então pelo menos no .NET 3.5 você pode definir ETag por meio de Response.Headers.Add e isso funciona bem.

N. B.se você fizer isso, terá que implementar você mesmo a comparação dos cabeçalhos do cliente e o tratamento da resposta HTTP 304 - não tenho certeza se o .NET cuida disso para você em circunstâncias normais.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top