OutputCache está enviando um cabeçalho Vary errado quando a chamada atinge o cache
Tenho um método de ação que quero armazenar em cache:
[OutputCache(Duration=60*5, Location=OutputCacheLocation.Any, VaryByCustom="index")]
public ActionResult Index()
{
return View();
}
Com esta abordagem:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
context.Response.Cache.SetOmitVaryStar(true);
context.Response.Cache.VaryByHeaders["Cookie"] = true;
if (User.Identity.IsAuthenticated)
{
Debug.Print("Authenticated");
context.Response.Cache.SetNoServerCaching();
context.Response.Cache.SetCacheability(HttpCacheability.Private);
return null;
}
else
{
Debug.Print("Non authenticated");
return custom;
}
}
A ideia era mantenha uma versão em cache da página para usuários não autenticados, mas evite o cache para usuários autenticados.
Eu pensei que sempre retornaria umVary:Cookie
Cabeçalho HTTP, mas não é. Fazendo um teste com o Fiddler e emitindo duas vezes a mesma solicitação, na primeira chamada HTTP, ele funciona bem:
HTTP/1.1 200 OK
Cache-Control: public, max-age=300
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 10:53:36 GMT
Last-Modified: Thu, 09 Feb 2012 10:48:36 GMT
Vary: Cookie
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 10:48:37 GMT
Content-Length: 441
Mas no segundo, ele substitui o cabeçalho:
HTTP/1.1 200 OK
Cache-Control: public, max-age=297
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 10:53:36 GMT
Last-Modified: Thu, 09 Feb 2012 10:48:36 GMT
Vary: *
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 10:48:39 GMT
Content-Length: 441
Então, até onde eu sei, os navegadores não armazenarão em cache a solicitação, mesmo que seja pública, poisVary:*
significa que a solicitação foi gerada com parâmetros que não estão na URL nem nos cabeçalhos HTTP. Existe uma maneira de corrigir isso
Saudações
ATUALIZAR
De maneira semelhante, quando envio duas solicitações autenticadas idênticas, a primeira chamada recebe oprivate
modificador, mas não oVary
cabeçalho:
HTTP/1.1 200 OK
Cache-Control: private, max-age=300
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 12:43:14 GMT
Last-Modified: Thu, 09 Feb 2012 12:38:14 GMT
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 12:38:14 GMT
Content-Length: 443
Mas o segundo obtém a mesma resposta que uma solicitação não autenticada:
HTTP/1.1 200 OK
Cache-Control: public, max-age=298
Content-Type: text/html; charset=utf-8
Expires: Thu, 09 Feb 2012 12:44:32 GMT
Last-Modified: Thu, 09 Feb 2012 12:39:32 GMT
Vary: *
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 09 Feb 2012 12:39:33 GMT
Content-Length: 443
Fiz upload de umtest projeto mostrando o problema pode ser que você queira experimentá-l
Esteja ciente de que existe umIHttpModule
que define uma solicitação como autenticada ou não, dependendo se a solicitação possui um cookie ou não, essa não é uma abordagem da "vida real", é apenas para fins de test
O projeto contém apenas uma página da web com um link para si mesmo, um link que efetua login e outro link que efetua logout:
LogIn: envia um cookie em umHTTP 302
redirecionamento para a página inicial novamentLogOut: envia um cookie expirado em umHTTP 302
redirecionamento para a página inicial novamentO esperado / ideal o comportamento seria:
Índice de acesso do usuário e obtenha a página do servidor. A página mostra a data "A". Índice de acesso do usuário novamente e o navegador mostra a versão em cache. A página mostra a data "A"impe o cache do navegado Índice de acesso do usuário novamente e o navegador mostra a versão em cache do servidor. A página mostra a data "A". usuário clica no login e o broswer recebe uma nova página, que mostra a data "B" usuário clica em logout e o navegador obtém a página em cache do servidor. A página mostra a data "A" novamente.Mas este é o comportamento até agora:
Índice de acesso do usuário e obtenha a página do servidor. A página mostra a data "A". Índice de acesso do usuário novamente e o navegador mostra a versão em cache. A página mostra a data "A"impe o cache do navegado Índice de acesso do usuário novamente e o navegador mostra a versão em cache do servidor. A página mostra a data "A". usuário clica no login e o broswer recebe uma nova página, que mostra a data "B" usuário clica em logout e o navegador deve obter a página em cache do servidor, mas não. A página mostra a data "B" novamente no cache do navegador. Isso ocorre porque a falta doVary
cabeçalho na resposta autenticad Não sei se entendi algo errado sobre o cache, faltando apenas alguns detalhes ou oOutputCache
não funciona muito bem, mas gostaria de receber qualquer orientação.
Felicidades
UPDATE 2:
Minha intenção é usar a semântica do cache HTTP para:
Permitir que navegadores e proxys armazenem em cache a versão "pública" da páginPermitir que os navegadores armazenem em cache a versão "autenticada" da página para seu usuáriSe eu alterar a declaração OutputCache para fazer o cache apenas no servidor e impedir o cache downstream e do cliente:
[OutputCache(Duration=60*5, Location=OutputCacheLocation.Server, VaryByCustom="index")]
se comporta conforme o esperado, mas o cache downstream e o cliente são impedidos, e não é isso que eu quer