错误请求 (400) Cache-Control 的最佳实践

Best practice of Cache-Control for Bad Request (400)

目前我有以下操作会告诉客户端将响应缓存 1200 秒:

[ResponseCache(Location = ResponseCacheLocation.Client, Duration = 1200)]
[HttpGet("universities")]
public IActionResult GetAllUniversities(string location)
{
    if (/*location not found*/)
      return BadRequest();

    ...
    return Ok(universities);
}

在响应 header 中,当它 returns Ok (200) 时,我收到以下值:

Cache-Control: private, max-age=1200

正如预期的那样完美。

当我将错误的位置传递给 API 和 API returns BadRequest (400) 时,它也 returns 相同 Cache-Control 值同上。

我的问题是,这是最佳做法吗?还是应该 return no-cache, no-store 而不是 400?如果应该,我如何 return private, max-age=1200 当它是 200 和 return no-cache, no-store 在 .NET Core 中仅用于此特定操作?

您应该在 ASP.NET Core 中使用 Response Caching Middleware,它只缓存 200 个状态代码响应的响应并忽略其他错误响应。

有关如何实施的更多信息,请参阅 - https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?tabs=aspnetcore2x

因为我需要满足以下条件:

  1. 如果响应代码不是 200,则不 return 响应缓存 header 值。
  2. Returns private, max-age=1200 如果响应代码为 200。
  3. 该解决方案应仅应用于某些控制器操作。

所以我决定创建一个实现 IResultFilter 的属性 class。

public sealed class PrivateCacheControlResultFilterAttribute : Attribute, IResultFilter
{
    public void OnResultExecuted(ResultExecutedContext context)
    {
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        context.HttpContext.Response.OnStarting(state =>
        {
            var httpContext = ((ResultExecutingContext)state).HttpContext;

            if (httpContext.Response.StatusCode == 200)
                httpContext.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
                {
                    Private = true,
                    MaxAge = TimeSpan.FromSeconds(1200)
                };
            return Task.CompletedTask;
        }, context);
    }
}

然后在 GetAllUniversities 操作上使用这个新属性。

[PrivateCacheControlResultFilter]
[HttpGet("universities")]
public IActionResult GetAllUniversities(string location)
{
    if (/*location not found*/)
      return BadRequest();

    ...
    return Ok(universities);
}