考虑ASP.NET Core的ResponseBufferingMiddleware:
public class ResponseBufferingMiddleware
{
private readonly RequestDelegate _next;
public ResponseBufferingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
var originalResponseBody = httpContext.Response.Body;
// no-op if buffering is already available.
if (originalResponseBody.CanSeek)
{
await _next(httpContext);
return;
}
var originalBufferingFeature = httpContext.Features.Get<IHttpBufferingFeature>();
var originalSendFileFeature = httpContext.Features.Get<IHttpSendFileFeature>();
try
{
// Shim the response stream
var bufferStream = new BufferingWriteStream(originalResponseBody);
httpContext.Response.Body = bufferStream;
httpContext.Features.Set<IHttpBufferingFeature>(new HttpBufferingFeature(bufferStream, originalBufferingFeature));
if (originalSendFileFeature != null)
{
httpContext.Features.Set<IHttpSendFileFeature>(new SendFileFeatureWrapper(originalSendFileFeature, bufferStream));
}
await _next(httpContext);
// If we're still buffered, set the content-length header and flush the buffer.
// Only if the content-length header is not already set, and some content was buffered.
if (!httpContext.Response.HasStarted && bufferStream.CanSeek && bufferStream.Length > 0)
{
if (!httpContext.Response.ContentLength.HasValue)
{
httpContext.Response.ContentLength = bufferStream.Length;
}
await bufferStream.FlushAsync();
}
}
finally
{
// undo everything
httpContext.Features.Set(originalBufferingFeature);
httpContext.Features.Set(originalSendFileFeature);
httpContext.Response.Body = originalResponseBody;
}
}
}
为什么这不是内存泄漏?他们创建了一个新的BufferingWriteStream(https://github.com/aspnet/BasicMiddleware/blob/dev/src/Microsoft.AspNetCore.Buffering/BufferingWriteStream.cs),但从不处理它。 HTTP Pipeline在完成请求之后会自动处理流吗?
答案 0 :(得分:3)
此流只是您在其构造函数中传递的其他流的包装器(在本例中为originalResponseBody
)。因此 - 没有必要处理它 - 它本身不包含任何可以清除\释放的非托管资源,也不包含它应该处理的任何其他一次性组件,因此没有理由它实现{{1但它继承自已实现它的类。它只是通过一些额外的逻辑(缓冲)将所有IDisposable
方法(如Stream
等)代理到包装流中。