我可以检测我的HttpModule中是否已压缩内容吗?

时间:2011-03-25 15:51:34

标签: c# asp.net iis

我有一个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,因此我无法进行屏障检查。

感谢所有的想法。

2 个答案:

答案 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”,因此很容易检查压缩