可以在ASP.NET/IIS 7中有选择地禁用gzip压缩吗?

Kir*_*oll 10 c# compression asp.net iis-7 asp.net-mvc-3

我使用长期的异步HTTP连接通过AJAX向客户端发送进度更新.启用压缩时,不会以离散块的形式接收更新(出于显而易见的原因).禁用压缩(通过添加<urlCompression>元素<system.webServier>)确实解决了问题:

<urlCompression doStaticCompression="true" doDynamicCompression="false" />
Run Code Online (Sandbox Code Playgroud)

但是,这会在站点范围内禁用压缩.我想保留每个其他控制器和/或操作的压缩,除了这个.这可能吗?或者我将不得不用自己的web.config创建一个新的站点/区域?欢迎任何建议.

PS写入HTTP响应的代码是:

var response = HttpContext.Response;
response.Write(s);
response.Flush();
Run Code Online (Sandbox Code Playgroud)

Kir*_*oll 14

@Aristos的回答将适用于WebForms,但在他的帮助下,我已经采用了更符合ASP.NET/MVC方法的解决方案.

创建一个新的过滤器以提供gzipping功能:

public class GzipFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var context = filterContext.HttpContext;
        if (filterContext.Exception == null && 
            context.Response.Filter != null &&
            !filterContext.ActionDescriptor.IsDefined(typeof(NoGzipAttribute), true))
        {
            string acceptEncoding = context.Request.Headers["Accept-Encoding"].ToLower();;

            if (acceptEncoding.Contains("gzip"))
            {
                context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
                context.Response.AppendHeader("Content-Encoding", "gzip");
            }                       
            else if (acceptEncoding.Contains("deflate"))
            {
                context.Response.Filter = new DeflateStream(context.Response.Filter, CompressionMode.Compress);
                context.Response.AppendHeader("Content-Encoding", "deflate");
            } 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

创建NoGzip属性:

public class NoGzipAttribute : Attribute {
}
Run Code Online (Sandbox Code Playgroud)

使用web.config阻止IIS7进行gzipping攻击:

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

在Global.asax.cs中注册全局过滤器:

protected void Application_Start()
{
    ...
    GlobalFilters.Filters.Add(new GzipFilter());
}
Run Code Online (Sandbox Code Playgroud)

最后,使用NoGzip属性:

public class MyController : AsyncController
{
    [NoGzip]
    [NoAsyncTimeout]
    public void GetProgress(int id)
    {
        AsyncManager.OutstandingOperations.Increment();
        ...
    }

    public ActionResult GetProgressCompleted() 
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

PS再一次,非常感谢@Aristos,感谢他的有用的想法和解决方案.


Sev*_*in7 5

我找到了一种更简单的方法来做到这一点。您可以有选择地禁用默认的 IIS 压缩(假设它在您的 web.config 中启用),而不是有选择地进行自己的压缩。

只需删除请求中的接受编码编码头,IIS 就不会压缩页面。

(global.asax.cs:)

protected void Application_BeginRequest(object sender, EventArgs e)
{
    try
    {
        HttpContext.Current.Request.Headers["Accept-Encoding"] = "";
    }
    catch(Exception){}
}
Run Code Online (Sandbox Code Playgroud)

  • 在 *server* 端修改 *request* 标头是非常糟糕的做法。您基本上是在服务器上进行黑客攻击以伪造请求标头以修改服务器端行为。至少可以说,这很令人担忧。 (2认同)