我认为自己在C#方面做得很好,但我在理解下面这段代码时遇到了麻烦:
using (var memoryStream = new MemoryStream())
{
var responseStream = httpContext.Response.Body;
httpContext.Response.Body = memoryStream;
await this.next(httpContext);
using (var compressedStream = new GZipStream(responseStream, CompressionLevel.Optimal))
{
httpContext.Response.Headers.Add("Content-Encoding", new [] { "gzip" });
memoryStream.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(compressedStream);
}
}
此代码是从压缩HTTP响应的ASP.Net Core中间件中提取的,并且令人惊讶地"它可以工作......或者看起来似乎(我用Fiddler测试过它)。
首先让我理解:
httpContext.Response.Body
中的responseStream
。httpContext.Response.Body
替换memoryStream
引用。httpContext.Response.Body
引用原始responseStream
数据,而httpContext.Response.Body
新数据为空。this.next()
是等待的,我们的代码执行将会停止"停止"直到所有中间件都返回。GZipStream
,添加响应标头,并且"寻找"到memoryStream
。memoryStream
复制到compressedStream
,并将其写入responseStream
。那么,memoryStream
,compressedStream
和responseStream
之间的关系是什么?我们创建compressedStream
以写入responseStream
,然后最终写入httpContext.Response.Body
,但responseStream
到httpContext.Response.Body
的引用不再存在?
答案 0 :(得分:1)
现在,OOB ResponseCompressionMiddleware
看起来有些不同。
但是在您粘贴的示例中,我将注释说明为什么memoryStream
在复制到compressedStream
时实际上并不为空。
using (var memoryStream = new MemoryStream()) // Create a buffer so we can capture response content written by future middleware/controller actions
{
var responseStream = httpContext.Response.Body; // save a reference to the ACTUAL STREAM THAT WRITES TO THE HTTP RESPONSE WHEN WRITTEN TO.
httpContext.Response.Body = memoryStream; // replace HttpContext.Response.Body with our buffer (memoryStream).
await this.next(httpContext); // <== somewhere in here is where HttpContext.Response.Body gets written to, and since Body now points to memoryStream, really memoryStream gets written to.
using (var compressedStream = new GZipStream(responseStream, CompressionLevel.Optimal)) // Here is where we wrap the ACTUAL HTTP RESPONSE STREAM with our ready-to-write-to compressedStream.
{
httpContext.Response.Headers.Add("Content-Encoding", new [] { "gzip" });
memoryStream.Seek(0, SeekOrigin.Begin); // Previously, we set HttpContext.Response.Body to a memoryStream buffer, then SOMEONE in the middleware chain or controller action wrote to that Body, we can seek to the beginning of what they wrote, and copy that content to the compressedStream.
await memoryStream.CopyToAsync(compressedStream);
}
}
希望有帮助。
答案 1 :(得分:0)
代码简单地将管道中的下一个中间件写入memoryStream
对象并压缩它,以便在此中间件运行之前使用responseStream
中的任何内容响应客户端。
现有的responseStream
内容+ memoryStream
内容。