.NET Core MVC中的UseExceptionHandler()中间件可防止设置响应标头

时间:2018-07-30 19:12:51

标签: asp.net-core asp.net-core-mvc

Startup.cs

// ...
app.Use(async (context, next) =>
{
    context.Response.Headers.Add("X-Frame-Options", "DENY");
    context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
    context.Response.Headers.Add("Server", "ololo");

    await next();
});

if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); }
else { app.UseExceptionHandler("/Home/Error"); }

app.UseStaticFiles();
app.UseAuthentication();
// ...

一切正常后,按预期方式获得以下标题:

HTTP/1.1 200 OK
Connection: close
Date: Mon, 30 Jul 2018 18:39:33 GMT
Content-Type: text/html; charset=utf-8
Server: ololo
Transfer-Encoding: chunked
X-Frame-Options: DENY
X-Content-Type-Options: nosniff

因此ServerX-Frame-OptionsX-Content-Type-Options标头被覆盖。

但是如果我的代码中有未处理的异常,那么我会得到以下标头:

HTTP/1.1 500 Internal Server Error
Connection: close
Date: Mon, 30 Jul 2018 18:35:49 GMT
Content-Type: text/html; charset=utf-8
Server: Kestrel
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Expires: -1

因此标头不会被覆盖。

那是为什么?是设计使然吗?例外中间件的工作方式是否不同,因此不会贯穿整个流程?

dotnet --info
.NET Command Line Tools (2.1.4)

Product Information:
 Version:            2.1.4
 Commit SHA-1 hash:  5e8add2190

Microsoft .NET Core Shared Framework Host

  Version  : 2.0.5
  Build    : 17373eb129b3b05aa18ece963f8795d65ef8ea54

1 个答案:

答案 0 :(得分:2)

在任何情况下,设置标头的一种更可靠的方法是使用OnStarting回调。参见docs

  

添加将在响应标头发送到客户端之前要调用的委托。

public async Task Invoke(HttpContext context)
{
    context.Response.OnStarting(() =>
    {
        context.Response.Headers.Add("X-Frame-Options", "DENY");
        context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
        context.Response.Headers.Add("Server", "ololo");

        return Task.CompletedTask;
    });

    await _next(context);
}

OnStarting将在响应标头写入连接之前被调用。这允许您在异常中间件处理完标头之后设置标头