Iis 7 自定义IIS模块与gzip冲突

Iis 7 自定义IIS模块与gzip冲突,iis-7,httpmodule,Iis 7,Httpmodule,作为一个实验,我一直在考虑创建一个IIS管理的模块来动态修改CSS文件。背后的故事是,所有的web应用程序都保留一个共享的通用版本号,我们将其附加到每个JS、CSS和图像引用(HTML)中,我想修改CSS的实际内容,以便也将版本号附加到CSS中的图像引用中。例如: span.warning { background-image: url(warning-icon.png) } 应成为: span.warning { background-image: url(warning-icon.png?

作为一个实验,我一直在考虑创建一个IIS管理的模块来动态修改CSS文件。背后的故事是,所有的web应用程序都保留一个共享的通用版本号,我们将其附加到每个JS、CSS和图像引用(HTML)中,我想修改CSS的实际内容,以便也将版本号附加到CSS中的图像引用中。例如:

span.warning { background-image: url(warning-icon.png) }
应成为:

span.warning { background-image: url(warning-icon.png?123) }
现在,我知道有很多不同的方法来解决这个问题(有些可能更好),但我想知道是否有人能回答我提出的与我一直在玩的问题相关的问题

到目前为止,我已经了解到托管HTTP模块不能直接修改响应流(我认为),正确的方法是附加一个完成这项工作的输出过滤器蒸汽。我编写了以下测试模块:

public class HttpCSSModule : IHttpModule
{

    public void Init(HttpApplication httpApplication)
    {
        httpApplication.BeginRequest += new EventHandler(
            (s, e) => AttachFilter((HttpApplication)s));
    }

    private void AttachFilter(HttpApplication httpApplication)
    {
        HttpRequest httpRequest = httpApplication.Context.Request;
        HttpResponse httpResponse = httpApplication.Context.Response;
        if (httpRequest.Path.EndsWith(".css", StringComparison.CurrentCultureIgnoreCase))
        {
            if (!string.IsNullOrEmpty(httpRequest.Url.Query))
            {
                httpResponse.Filter = new CSSResponseStreamFilter(
                    httpResponse.Filter, httpRequest.Url.Query);
            }
        }
    }

    public void Dispose()
    {
    }

    private class CSSResponseStreamFilter : Stream
    {

        private Stream inner;
        private string version;
        private MemoryStream responseBuffer = new MemoryStream();

        public CSSResponseStreamFilter(Stream inner, string version)
        {
            this.inner = inner;
            this.version = version;
        }

        public override void Close()
        {

            if (responseBuffer.Length != 0)
            {

                string stylesheet = Encoding.ASCII.GetString(
                    responseBuffer.GetBuffer(), 0, (int)responseBuffer.Length);

                // crude, just testing
                string versionedStylesheet = stylesheet.
                    Replace(".png", ".png" + version).
                    Replace(".jpg", ".jpg" + version).
                    Replace(".gif", ".gif" + version);

                byte[] outputBytes = Encoding.ASCII.GetBytes(versionedStylesheet);
                innerStream.Write(outputBytes, 0, outputBytes.Length);

            }

            innerStream.Close();

        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            responseBuffer.Write(buffer, offset, count);
        }            

        // other Stream members

    }

}
该模块可以工作,但并不总是如此,有些事情我不明白。最大的问题是,当打开静态文件压缩时,模块无法工作。当打开静态文件压缩时,对CSS文件的第一个请求将像往常一样提供该文件,但IIS可能会保留Gzip版本,并且在任何后续请求中,我的自定义流都会传递Gzip流。我还没有找到一种方法来检测它,但可能有一个更深层次的问题,我可能真的不知道IIS模块应该如何工作。我的模块应该对另一个模块做出任何假设,或者至少应该能够定义它们在IIS配置中处理请求的顺序,这似乎是错误的。但是,这似乎没有意义,因为每个模块都可以注册以处理请求生命周期中的任何事件

因此,如果我必须将我的想法重新表述为更精确的问题,那么问题将是:


如何确保在StaticFileModule模块读取文件并将其发送到服务器之后,但在StaticCompressionModule之前调用我的后处理/模块?这个问题有意义吗?根据上面的观察,这似乎有点矛盾。

静态文件压缩的配置包括特定的文件或mime类型,我忘了是哪一种。如果您想使用静态压缩,它只需要在实际上是静态的文件上。使用HttpModule重写它们意味着它们不再是静态的。因此,您可以对这些文件类型使用动态压缩,并且正如您所期望的那样,您需要确保动态压缩将包括适当的mime类型或文件扩展名。

您是对的。这就解决了问题,而且它实际上更符合逻辑(不再是静态文件)。这还表明,动态压缩模块(compdyn.dll)和静态压缩模块(compstat.dll)的区别不仅仅在于它们处理的类型列表。它们必须以不同的方式集成到IIS管道中。我也有同样的问题,我正在花几个小时来解决它:你能给我解释一下你是如何解决这个问题的吗?