TL; DR 我有一个ASP.NET 5(MVC 6)应用程序,想要设置HTTP Content-Length头以避免分块响应。
令我惊讶的是,在ASP.NET 5中实现这个任务相当棘手。一切都在运行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
流并额外计算字节数并不起作用,因为微软团队指出 一旦他们愿意缓冲的数据量被写入,它就会被发送到网络上,他们不再存储它, 所以我最多只能在最后一个块中添加 Content-Length,这不是期望的行为 - 我想完全避免分块。
非常感谢任何帮助!
p.s. 我知道分块是 HTTP/1.1 的常规功能,但在我的情况下,它会降低性能,所以我想避免它,同时又不强制客户端发送 HTTP/1.0 请求。
toString()
,然后设置Response.Headers.Append("Content-Length", retVal.Length.ToString())
。其中一些方法返回IEnumerable
(即,一些集合),其他方法返回IActionResult
等。MVC在某个地方已经对响应执行了序列化,然后返回它,如果可能的话,我想抓取那个序列化的响应,并设置Content-Length头。 - Miljen Mikic