繁体   English   中英

在 ASP.NET 5 响应中设置 Content-Length 标头

[英]Setting Content-Length header in ASP.NET 5 response

TL; DR我有一个 ASP.NET 5 (MVC 6) 应用程序,只是尝试设置 HTTP Content-Length 标头以避免分块响应。

令我惊讶的是,这恰好是在 ASP.NET 5 中完成的一项非常棘手的任务。一切都在 Kestrel 上运行,Kestrel 来自 ASP.NET 5 Beta7, 当没有为响应指定内容长度时,它支持自动编写分块响应

还有一个类似的问题在这里,但不同的是,OP只是想算的响应大小,而我需要确保的Content-Length头的响应中发送。 到目前为止尝试了很多东西,唯一有效的是编写自定义中间件:

public class WebApiMiddleware {
    RequestDelegate _next;

    public WebApiMiddleware(RequestDelegate next) {
        _next = next;
    }

    public async Task Invoke(HttpContext context) {
         using (var buffer = new MemoryStream()) {
            var response = context.Response;

            var bodyStream = response.Body;
            response.Body = buffer;

            await _next(context);

            response.Headers.Add("Content-Length", new[] { buffer.Length.ToString()});
            buffer.Position = 0;
            await buffer.CopyToAsync(bodyStream);
        }
     }
}

然而,这是非常低效的,因为我们在处理每个请求时都在使用额外的内存。 使用仅环绕context.Response.Body流并额外计算字节的自定义流不起作用,因为 Microsoft 团队表示,一旦他们愿意缓冲的数据量已写入,它就会在线路上消失并且他们不再存储它,所以我最多可以将 Content-Length 添加到最后一个块,这不是所希望的行为 - 我想完全避免分块。

任何帮助表示高度赞赏!

ps 我知道分块是 HTTP/1.1 的常规功能,但在我的场景中它会降低性能,所以我想避免它而不强制客户端发送 HTTP/1.0 请求。

您需要在发送响应之前发送标头,因此您需要在发送之前存储整个响应以确定长度。

正如您所说, context.Response.Body流在发送之前不会存储太多,因此开销并不大。

有做类似事情的中间件: https : //github.com/aspnet/BasicMiddleware/blob/master/src/Microsoft.AspNetCore.Buffering/ResponseBufferingMiddleware.cs它与您编写的非常相似,但支持IHttpBufferingFeature等附加功能允许其他中间件控制缓冲。

检查bufferStream.CanSeek是为了确保没有人已经将响应流包装到缓冲流中并避免双缓冲。

对于您的第二个问题:这个地方是中间件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM