我有一个HttpModule,用于动态压缩来自ASP.NET(MVC3)Web应用程序的内容。该方法与this article中的CompressionModule非常相似(模块将GZip过滤器应用于HttpResponse并设置正确的内容编码标头)。
出于某种原因,这需要在经典模式下运行,而不是集成管道模式。
我遇到的问题是,在某些启用了IIS压缩的服务器上,IIS会压缩内容然后我的模块会压缩它。
结果是我将内容压缩了两次,编码为:
Content-encoding: gzip,gzip
一个来自IIS,一个来自我的代码中的这一行:
httpResponse.AppendHeader("Content-encoding", "gzip");
有没有人知道在经典模式下,我可以检查内容是否已经压缩,或如果在服务器上启用压缩,以绕过我自己的压缩?
在管道模式下,此检查就像
一样简单if (httpResponse.Headers["Content-encoding"]!= null)
{
return;
}
即。检查是否已经设置了内容编码,如果有,则不执行任何操作。
然而,我在经典模式中难倒。不幸的是,在经典模式下不允许访问HttpResponse.Headers
,因此我无法进行屏障检查。
感谢所有的想法。
答案 0 :(得分:2)
从理论上讲,你可以使用反射来查看HttpRequest._cacheHeaders
字段,其中ASP.NET显然以经典模式存储所有尚未发送的标题:
if (this._wr is IIS7WorkerRequest)
{
this.Headers.Add(HttpResponseHeader.MaybeEncodeHeader(name), HttpResponseHeader.MaybeEncodeHeader(value));
}
else if (flag)
{
if (this._cacheHeaders == null)
{
this._cacheHeaders = new ArrayList();
}
this._cacheHeaders.Add(new HttpResponseHeader(knownResponseHeaderIndex, value));
}
答案 1 :(得分:1)
我找到了一种相对简单的方法来检查输出是否已经压缩;我的方法即使在经典模式下运行IIS也能正常工作,尽管它可能被认为是“黑客”,但我发现它工作得非常一致;这个想法或多或少是以下
// checks if the response is already compressed
private bool IsResponseCompressed(HttpApplication app)
{
string filter = app.Response.Filter.ToString().ToLower();
if (filter.Contains("gzip") | filter.Contains("deflate"))
{
return true;
}
return false;
}
基本上代码通过检查响应过滤器名称来工作;如果输出流被压缩,则名称包含“gzip”或“deflate”,因此很容易检查压缩