【问题标题】:How response headers be sent to the client when the middleware pipeline hasn't finished?中间件管道未完成时如何将响应标头发送到客户端?
【发布时间】:2021-09-21 17:27:52
【问题描述】:

我正在阅读一本书,其中显示ExceptionHandlerMiddleware 重新执行中间件管道以生成发送给用户的响应(使用app.UseExceptionHandler("/Error");):

作者说:

重新执行中间件管道是保持网络一致性的好方法 错误页面的应用程序,但有一些问题需要注意。一、中间件可以 仅在响应尚未生成时才修改在管道中进一步生成的响应 发送给客户。这可能是一个问题,例如,当 ASP.NET Core 运行时发生错误 向客户端发送静态文件。在这种情况下,字节已经开始发送, 错误处理中间件将无法运行,因为它无法重置响应。

我对“字节已经开始发送,错误处理中间件将无法运行”部分感到困惑。

假设我们将管道构建为:

假设一个客户端正在请求一个css文件,我对静态文件中间件的理解是,这个中间件读取wwwroot文件夹中的相应文件并将css文件的内容写入HttpContext.Response,所以即使是错误发生并且中途抛出异常,仅表示HttpContext.Response(在静态文件中间件中)不完整,由于ExceptionHandlerMiddleware必须使用try和catch来等待Task,ExceptionHandlerMiddleware会捕获这个异常,所以当 ExceptionHandlerMiddleware 检测到它下面的中间件抛出了异常时,ExceptionHandlerMiddleware 可以重新执行新路径 /Error 的管道。

那么静态文件中间件是如何在控件回退到ExceptionHandlerMiddleware之前向客户端发送响应的呢?向客户端发送响应不是 Kestrel Web 服务器或反向代理的工作吗?

【问题讨论】:

  • 能否在此处分享您的代码,以便我们为您重现该问题。

标签: c# .net asp.net-core asp.net-core-middleware


【解决方案1】:

有几点可以帮助你得到答案:

1-ASP.NET Core does not buffer the HTTP response body。第一次写响应:

  • 标头与正文的该块一起发送到客户端。
  • 无法再更改响应标头。

2- HasStarted 是 HTTPResponse 中的一个属性,指示是否已将响应标头发送到客户端。

3- 组件只有在能够处理和操纵响应时才会被调用。

因此,将所有三点放在一起意味着: 当开始发送静态文件时,HasStarted 属性设置为 true。在那之后,您不能调用 next() (在当前请求的上下文中),因为响应已经开始。但是,如果我们使用重定向而不是重新执行,这将是一个不同的请求,我们可以生成所需的响应。

【讨论】:

    猜你喜欢
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 2019-05-22
    相关资源
    最近更新 更多