在使用dynamicCompressionBeforeCache缓存之前重写asp.net响应

And*_*vey 7 asp.net

我的ASP.NET库安装了一个响应过滤器来解析和更改页面的HTML输出.这是有效的,直到在web.config中启用以下内容:

<system.webServer>
    <urlCompression doDynamicCompression="true" dynamicCompressionBeforeCache="true" />
</system.webServer>
Run Code Online (Sandbox Code Playgroud)

我的响应过滤器仍然被调用,但传递的似乎是压缩数据,而不是原始HTML.

如何在页面存储到输出缓存之前确保重写?

将dynamicCompressionBeforeCache设置为false不是一个选项,因为此库旨在用于其他人可能有充分理由启用压缩的Web应用程序中.

And*_*vey 5

alexb的回答帮助我找到了解决方案.

关键是意识到我的响应过滤器在IIS DynamicCompressionModule之后运行.这可以通过在请求处理程序执行后立即刷新响应来强制运行过滤器来解决.

public class MyModule : IHttpModule
{
    public void Init(HttpApplication application)
    {
        application.BeginRequest += application_BeginRequest;
        application.PostRequestHandlerExecute += application_PostRequestHandlerExecute;
    }

    void application_BeginRequest(object sender, EventArgs e)
    {
        // Install response filter
        var response = ((HttpApplication)sender).Context.Response;
        response.Filter = new RewritingFilter(response.Filter);
    }

    void application_PostRequestHandlerExecute(object sender, EventArgs e)
    {
        // Flush immediately after the request handler has finished.
        // This is Before the output cache compression happens.
        var response = ((HttpApplication)sender).Context.Response;
        response.Flush();
    }

    public void Dispose()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*exB 3

根据这篇博客文章,负责处理动态压缩的 DynamicCompressionModule 在 ReleaseRequestState 阶段运行(该阶段发生在 UpdateRequestCache 阶段之前,此时页面被存储到输出缓存)。所以:

  • 如果您想在执行动态压缩之前处理响应,那么您应该将过滤代码放置在连接到 PostRequestHandlerExecute 事件的 HttpModule 中;
  • 如果您想处理响应缓存,但在压缩之后,那么您应该将过滤代码放在挂钩 PostReleaseRequestState 事件的 HttpModule 中。

以下是有关如何执行此操作的示例:

public class SampleModule : IHttpModule
{
    public void Dispose()
    {
        return;
    }

    public void Init(HttpApplication context)
    {
        context.PostRequestHandlerExecute += new EventHandler(App_OnPostRequestHandlerExecute);
        context.PostReleaseRequestState += new EventHandler(App_OnPostReleaseRequestState);
    }

    private void App_OnPostRequestHandlerExecute(object sender, EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;
        HttpResponse response = app.Context.Response;

        response.Write("<b>Modified!</b>");
    }

    private void App_OnPostReleaseRequestState(object sender, EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;
        HttpResponse response = app.Context.Response;

        //check if the output has been compressed - make sure to actually test if for whatever content encoding you want to deal with
        if (response.Headers["Content-Encoding"] != null)
        {
            //do stuff
        }
        else
        {
            //do some other stuff
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用 web.config 文件注册您的模块:

<add name="SampleModule" type="My.ModuleNamespace.SampleModule" />
Run Code Online (Sandbox Code Playgroud)