Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Content-encoding" header disappears from HttpHandler response if an exception occurs

I have a custom HttpHandler in which I manually enable output compression, like so:

context.Response.AppendHeader("Content-encoding", "gzip");
context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);

This works nicely for most requests, but when an exception is encountered the "Content-encoding" header disappears from the response, while the compression filter remains in place. The result is that the error page is gzip compressed, but the browser receives no header indicating that fact. The browser then tries to display the still-compressed data as text, which is gobbledygook.

Full test case code is shown below. Try alternately disabling the compression or not throwing the exception.

Can anyone shed some light on why the "Content-encoding" header disappears?

I suppose I could simply enable compression as the last thing the handler does, so that if an exception is encountered it never reaches the point where the compression filter is added; but the behavior I'm seeing strikes me as a bug. Can anyone confirm?

public class TestHandler : IHttpHandler 
{
    public void ProcessRequest(HttpContext context)
    {
        CompressResponse(context);
        context.Response.Write("Hello world");

        // Throw an exception for testing purposes
        throw new Exception("Just testing...");
    }

    private void CompressResponse(HttpContext context)
    {
        string acceptEncoding = context.Request.Headers["Accept-Encoding"];
        if (String.IsNullOrEmpty(acceptEncoding))
        {
            return;
        }

        // gzip or wildcard
        if (acceptEncoding.ToLower().Contains("gzip") || acceptEncoding.Contains("*"))
        {
            context.Response.AppendHeader("Content-encoding", "gzip");
            context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
            return;
        }

        // Also handles deflate (not shown here)
        // <snip>
    }

    public bool IsReusable
    {
        get { return true; }
    }
}

EDIT: Screenshot of the still-encoded response I'm seeing with my test case: http://i.imgur.com/49Vcl.png

like image 551
David Mills Avatar asked Jan 12 '12 23:01

David Mills


1 Answers

I had the same thing happen when forcing gzip on a WebForms application. In order to fix it I had to clear the filter in the Application_Error method in Global.asax.cs

protected void Application_Error(Object sender, EventArgs e)
{
    Response.Filter = null;
}

The reason this is happening is b/c the filter is being set before the app has an error. And for some reason the yellow screen error message clears the Content-encoding header but doesn't do anything to the response filter.

like image 55
Josh Allen Avatar answered Oct 10 '22 05:10

Josh Allen