如何防止对已压缩的响应进行默认 IIS 压缩?

发布于 2024-12-20 20:45:11 字数 2070 浏览 1 评论 0原文

TLDR

我有一个执行压缩的 IHttpHandler 。它本身工作得很好。但后来我添加了一个 IHttpModule,它对这些(以及所有其他)响应执行完全不相关的任务,现在 IIS 正在重新压缩已经压缩的响应。我怎样才能防止这种情况发生?

整个故事

我有一个 IHttpHandler 实现,它对 CSS 和 JS 文件执行组合和压缩(除其他外)。 IHttpHandler 中的所有内容都按照我想要的方式工作。

但后来我添加了一个 IHttpModule 实现,从 all 中删除不必要的响应标头(ServerX-AspNet-Version 等) PreSendRequestHeaders 事件期间的 响应(包括由 IHttpHandler 生成的动态响应)。

然而,似乎简单地注册一个IHttpModule,无论它实际做什么,都会导致 IIS 对响应应用压缩,即使响应已经被压缩。

因此,我的 IHttpHandler 显式压缩响应并设置 Content-Encoding 标头,然后(当且仅当)IHttpModule 也已注册, IIS 重新压缩响应(因此存在浏览器无法读取的双重压缩响应)。

我不想禁用所有默认压缩。我仍然希望视图中的 HTML 被压缩(并且我希望任何不经过 IHttpHandler 的 CSS 和 JS 也被默认压缩)。

我猜我的问题没有简单的解决方案,因为它看起来像是 IIS 中的一个错误。 IIS 不应压缩已压缩的响应。

我尝试将以下内容添加到我的 web.config 中,但没有效果:(

<httpCompression>
    <dynamicTypes>
        <add mimeType="text/css" enabled="false" />
        <add mimeType="application/javascript" enabled="false" />
    </dynamicTypes>
</httpCompression>

根据我对 文档,应该禁用动态生成的 CSS 和 JS 的压缩。)

我也尝试过这个,但没有效果:(

<httpCompression>
    <dynamicTypes>
        <clear/>
    </dynamicTypes>
    <staticTypes>
        <clear/>
    </staticTypes>
</httpCompression>

根据我对文档的解释,应该禁用所有默认压缩。)

更新

在​​我的IHttpHandler,我在最后调用context.Response.Flush。如果我删除此调用,响应不会得到双重压缩。我同意这个作为解决方案。谁能解释为什么会发生这种情况?

更新 2

我最好的猜测是,调用 Flush 会将响应置于 IIS 认为响应尚未压缩的状态(因此它应用默认压缩)。即使在我的模块中,我可以检查...

  • Response.Headers 包含 Content-Encoding 标头,并且
  • Response.Filter 不是-nullSystem.IO.Compression 类型之一。

不知道为什么 IIS 无法根据这些事实确定响应已经被压缩。

TLDR

I have an IHttpHandler that performs compression. It works fine on its own. But then I added an IHttpModule that performs a completely unrelated task on those (and all other) responses, and now IIS is re-compressing the already-compressed responses. How can I prevent this?

The Whole Story

I have an IHttpHandler implementation that performs combination and compression (among other things) for CSS and JS files. Everything in the IHttpHandler works exactly like I want it to.

But then I added an IHttpModule implementation that removes unnecessary response headers (Server, X-AspNet-Version, etc.) from all responses (including the dynamic responses that are generated by the IHttpHandler) during the PreSendRequestHeaders event.

However, it seems that simply registering an IHttpModule, regardless of what it actually does, causes IIS to apply compression to the response, even if the response is already compressed.

So, my IHttpHandler explicitly compresses the response and sets the Content-Encoding header, then (if and only if) the IHttpModule is also registered, IIS re-compresses the response (so there's a doubly-compressed response that browsers can't read).

I don't want to disable all default compression. I still want HTML from views to be compressed (and I want any CSS and JS that doesn't go through the IHttpHandler to also be default-compressed).

I'm guessing there's no easy solution to my problem because it seems like a bug in IIS. IIS should not compress a response that is already compressed.

I tried adding the following to my web.config, but it had no effect:

<httpCompression>
    <dynamicTypes>
        <add mimeType="text/css" enabled="false" />
        <add mimeType="application/javascript" enabled="false" />
    </dynamicTypes>
</httpCompression>

(From my interpretation of the documentation, that should disable compression for dynamically generated CSS and JS.)

I also tried this, to no effect:

<httpCompression>
    <dynamicTypes>
        <clear/>
    </dynamicTypes>
    <staticTypes>
        <clear/>
    </staticTypes>
</httpCompression>

(From my interpretation of the documentation, that should disable all default compression.)

Update

In my IHttpHandler, I call context.Response.Flush at the very end. If I remove this call, the response doesn't get double-compressed. I'm fine with this as a solution. Can anyone explain why this is happening?

Update 2

My best guess is that calling Flush puts the response into such a state that IIS doesn't think the response is already compressed (and so it applies default compression). Even though in my module I can check both...

  • that Response.Headers contains a Content-Encoding header and
  • that Response.Filter is non-null and is one of the System.IO.Compression types.

Not sure why IIS can't determine that the response is already compressed from those facts.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文