简体   繁体   English

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

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

TL; TL; DR I have an ASP.NET 5 (MVC 6) application and just trying to set a HTTP Content-Length header in order to avoid chunked response. DR我有一个 ASP.NET 5 (MVC 6) 应用程序,只是尝试设置 HTTP Content-Length 标头以避免分块响应。

To my surprise, it happens that this is a quite tricky task to accomplish in ASP.NET 5. Everything is running on Kestrel which from ASP.NET 5 Beta7 supports writing chunked responses automatically when no content length is specified for the response .令我惊讶的是,这恰好是在 ASP.NET 5 中完成的一项非常棘手的任务。一切都在 Kestrel 上运行,Kestrel 来自 ASP.NET 5 Beta7, 当没有为响应指定内容长度时,它支持自动编写分块响应

There is a similar question here , but the difference is that the OP just wants to count a response size, while I need to ensure that the Content-Length header is sent within a response.还有一个类似的问题在这里,但不同的是,OP只是想算的响应大小,而我需要确保的Content-Length头的响应中发送。 Tried with many things so far, and the only thing that works is writing a custom Middleware:到目前为止尝试了很多东西,唯一有效的是编写自定义中间件:

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

However, this is highly inefficient since we are using additional memory while processing every request.然而,这是非常低效的,因为我们在处理每个请求时都在使用额外的内存。 Using a custom stream that just wraps around the context.Response.Body stream and additionally counts bytes doesn't work since the Microsoft team states thatonce the amount of data they're willing to buffer has been written, it goes out on the wire and they don't store it any more , so I can, at best, add Content-Length to the last chunk which is not the wished behavior - I want to avoid chunking completely.使用仅环绕context.Response.Body流并额外计算字节的自定义流不起作用,因为 Microsoft 团队表示,一旦他们愿意缓冲的数据量已写入,它就会在线路上消失并且他们不再存储它,所以我最多可以将 Content-Length 添加到最后一个块,这不是所希望的行为 - 我想完全避免分块。

Any help is highly appreciated!任何帮助表示高度赞赏!

ps I am aware that chunking is a regular feature of HTTP/1.1, but in my scenario it degrades performance so I want to avoid it without forcing the clients to send HTTP/1.0 requests. ps 我知道分块是 HTTP/1.1 的常规功能,但在我的场景中它会降低性能,所以我想避免它而不强制客户端发送 HTTP/1.0 请求。

You need to send header before sending response so you need to store whole response before sending it to determine length.您需要在发送响应之前发送标头,因此您需要在发送之前存储整个响应以确定长度。

As you said context.Response.Body stream doesn't store to much before sending so overhead is not that big.正如您所说, context.Response.Body流在发送之前不会存储太多,因此开销并不大。

There is middleware that does similar thing: https://github.com/aspnet/BasicMiddleware/blob/master/src/Microsoft.AspNetCore.Buffering/ResponseBufferingMiddleware.cs it is very similar to what you wrote but supports additional features like IHttpBufferingFeature to allows other middleware control buffering.有做类似事情的中间件: https : //github.com/aspnet/BasicMiddleware/blob/master/src/Microsoft.AspNetCore.Buffering/ResponseBufferingMiddleware.cs它与您编写的非常相似,但支持IHttpBufferingFeature等附加功能允许其他中间件控制缓冲。

Checking for bufferStream.CanSeek is there to make sure nobody already wrapped response stream into buffering stream and avoid double buffering.检查bufferStream.CanSeek是为了确保没有人已经将响应流包装到缓冲流中并避免双缓冲。

For your second question: this place is middlware.对于您的第二个问题:这个地方是中间件。

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

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