gpt4 book ai didi

asp.net - 当调用命中缓存时,OutputCache 发送错误的 Vary header

转载 作者:可可西里 更新时间:2023-11-01 15:10:12 25 4
gpt4 key购买 nike

我有一个要缓存的操作方法:

[OutputCache(Duration=60*5, Location=OutputCacheLocation.Any, VaryByCustom="index")]
public ActionResult Index()
{
return View();
}

采用这种方法:

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

想法是 keep a cached version of the page for non-authenticated users, but avoid caching for authenticated ones .

我以为它总是会返回一个 Vary:Cookie HTTP header ,但事实并非如此。使用 Fiddler 进行测试并发出两次相同的请求,在第一个 HTTP 调用中一切顺利:

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

但在第二个中,它覆盖了 header :

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

因此,据我所知,浏览器不会缓存请求,即使它是公开的,因为 Vary:* 意味着请求是使用不在 URL 中的参数生成的也不在 HTTP header 中。有办法解决这个问题吗?

问候。

更新:

以类似的方式,当我发送两个相同的经过身份验证的请求时,第一个调用获得 private 修饰符,但不是 Vary header :

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

但是第二个得到的响应与未经身份验证的请求相同:

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

我上传了一个test project showing the issue所以您可能想尝试一下。

请注意,有一个 IHttpModule 可以根据请求是否有 cookie 将请求设置为经过身份验证,这不是“现实生活”的方法,它只是用于测试目的。

该项目仅包含一个网页,该网页带有指向自身的链接、一个让您登录的链接和另一个让您注销的链接:

  • 登录:再次将 HTTP 302 重定向中的 cookie 发送到主页。
  • 注销:再次向主页发送 HTTP 302 重定向中的过期 cookie。

预期/理想行为将是:

  1. 用户访问索引,并从服务器获取页面。页面显示日期“A”。
  2. 用户再次访问索引,浏览器显示缓存版本。页面显示日期“A”。
  3. 清理浏览器缓存。
  4. 用户再次访问索引,浏览器显示服务器缓存版本。页面显示日期“A”。
  5. 用户点击登录,浏览器得到一个新页面,显示日期“B”。
  6. 用户点击注销,浏览器获取服务器缓存页面。页面再次显示日期“A”。

但这是目前为止的行为:

  1. 用户访问索引,并从服务器获取页面。页面显示日期“A”。
  2. 用户再次访问索引,浏览器显示缓存版本。页面显示日期“A”。
  3. 清理浏览器缓存。
  4. 用户再次访问索引,浏览器显示服务器缓存版本。页面显示日期“A”。
  5. 用户点击登录,浏览器得到一个新页面,显示日期“B”。
  6. 用户点击注销,浏览器应该获取服务器缓存页面,但没有。该页面再次从浏览器缓存中显示日期“B”。这是因为经过身份验证的响应中缺少 Vary header 。

我不知道我是否在缓存方面犯了错误,只是遗漏了一些细节,或者 OutputCache 不能很好地工作,但我将不胜感激任何指导。

干杯。

更新 2:

我的意图是使用 HTTP 缓存语义来:

  1. 允许浏览器和代理缓存页面的“公开”版本。
  2. 允许浏览器为其用户缓存“经过身份验证”的页面版本。

如果我更改 OutputCache 声明以仅在服务器上进行缓存并阻止下游和客户端缓存:

[OutputCache(Duration=60*5, Location=OutputCacheLocation.Server, VaryByCustom="index")]

它的行为符合预期,但下游和客户端缓存被阻止,这不是我想要的。

最佳答案

我不认为 [OutputCache] 属性是你想要的,VaryByCustom 方法基本上是说我想根据这些参数缓存不同的版本,它实际上没有Do Not Cache 选项,并且该属性中的大部分代码都是围绕基于服务器的缓存构建的。

也就是说 MSDN 上的文档用于自定义缓存似乎表明您需要返回一个字符串以根据身份验证状态变化:

public override string GetVaryByCustomString(HttpContext context, string custom)
{
if(custom == "user") return "User:" + context.Request.User.Identity.Name;

return base.GetVaryByCustomString(context, custom);
}

然后在 VaryByCustom 中使用 user 文字:

[OutputCache(Duration=60*5, Location=OutputCacheLocation.Any, VaryByCustom="user")]
public ActionResult Index()
{
return View();
}

所以基本上这将导致为匿名(假设匿名身份是空字符串或其他东西)和服务器上的每个用户构建缓存,并将 Vary: * 发送到客户端我相信。显然您要找的东西并不理想。

如果您真的只想使用 HTTP 缓存来缓存未经身份验证的版本,我建议您不要使用 OutputCacheAttribute 并使用更多自定义内容。

您可以轻松地在自己的自定义属性中编写类似于您的 GetVaryByCustomString 实现的内容(这只是一些伪代码,需要的不止这些):

public class HttpCacheUnauthenticatedAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if(!filterContext.HttpContext.Request.IsAuthenticated) {
//TODO: set unauthenticated caching values and vary here
}
}
}

然后用它标记你的操作方法:

[HttpCacheUnauthenticated]
public ActionResult Index()
{
return View();
}

关于asp.net - 当调用命中缓存时,OutputCache 发送错误的 Vary header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9210581/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com