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