我认为自己在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测试它) .
让我先说明一下:
-
代码首先在
responseStream
中引用httpContext.Response.Body
. -
然后用新初始化的
memoryStream
替换httpContext.Response.Body
引用 . -
如果我对C#引用如何工作的理解,我说我们仍然使用
responseStream
引用原始httpContext.Response.Body
数据,而httpContext.Response.Body
新数据为空 . -
接下来,我们正在调用管道中的下一个中间件 .
-
因为
this.next()
是等待的,所以我们的代码执行将"stop",直到所有中间件都返回 . -
当我们的代码执行"resumes"时,它将初始化
GZipStream
,将响应头和"seeks"添加到memoryStream
的开头 . -
最后,它将内容或
memoryStream
复制到compressedStream
,将其写入responseStream
.
那么, memoryStream
, compressedStream
和 responseStream
之间的关系是什么?我们创建 compressedStream
以写入 responseStream
,然后最终写入 httpContext.Response.Body
,但是从 responseStream
到 httpContext.Response.Body
的引用不再存在了?
2 回答
FWIW OOB ResponseCompressionMiddleware现在看起来有点不同 .
但是在你粘贴的样本中,我将注释以说明为什么
memoryStream
在被复制到compressedStream
时实际上并不是空的 .希望有所帮助 .
代码简单地将管道中的下一个中间件写入
memoryStream
对象并压缩它,以便在此中间件运行之前用responseStream
中的任何内容响应客户端 .所以现有
responseStream
内容memoryStream
内容 .