[英]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.