friism
friism

Reputation: 19279

gzip compression for HTTP 1.0 proxy requests on Azure Web Sites

Is there any way to get Azure Web Sites to serve gzip'ed content for requests from a HTTP 1.0 proxy like Amazon Web Services CloudFront? Consider a request like this:

curl -I -H "accept-encoding: gzip,deflate,sdch" -H "Via: 1.0 {foo.cdn.net}" -0 http://{fooproject}.azurewebsites.net/

It seems that the general way to accomplish is to add the following element to system.webServer:

<httpCompression noCompressionForHttp10="false" noCompressionForProxies="false" />

It also seems that httpCompression is only valid in ApplicationHost.config and not web.config which means that it's not overwriteable on Azure Web Sites.

Any suggestions for workarounds?

Additional resources:

Upvotes: 5

Views: 898

Answers (3)

ianbeks
ianbeks

Reputation: 2228

IIS won't compress for HTTP/1.0 requests. You can override this behaviour by setting:

appcmd set config -section:system.webServer/httpCompression /noCompressionForHttp10:"False"

Upvotes: 1

ogggre
ogggre

Reputation: 2264

The auto-magical HTTP module that does the job is presented below. You need to register it in your Web.config file.

/// <summary>
/// Provides HTTP compression support for CDN services when
/// ASP.NET website is used as origin.
/// </summary>
public sealed class CdnHttpCompressionModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PreRequestHandlerExecute += Context_PreRequestHandlerExecute;
    }

    public void Dispose()
    {
    }

    void Context_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        var application = (HttpApplication)sender;
        var request = application.Request;
        var response = application.Response;

        // ---------------------------------------------------------------------

        bool allowed = false;

        string via = request.Headers["Via"];
        if (!string.IsNullOrEmpty(via))
        {
            if (via.Contains(".cloudfront.net"))
            {
                // Amazon CloudFront
                allowed = true;
            }

            // HINT: You can extend with other criterias for other CDN providers.
        }

        if (!allowed)
            return;

        // ---------------------------------------------------------------------

        try
        {
            if (request["HTTP_X_MICROSOFTAJAX"] != null)
                return;
        }
        catch (HttpRequestValidationException)
        {
        }

        // ---------------------------------------------------------------------

        string acceptEncoding = request.Headers["Accept-Encoding"];
        if (string.IsNullOrEmpty(acceptEncoding))
            return;

        string fileExtension = request.CurrentExecutionFilePathExtension;
        if (fileExtension == null)
            fileExtension = string.Empty;
        fileExtension = fileExtension.ToLowerInvariant();

        switch (fileExtension)
        {
            case "":
            case ".js":
            case ".htm":
            case ".html":
            case ".css":
            case ".txt":
            case ".ico":
                break;

            default:
                return;
        }

        acceptEncoding = acceptEncoding.ToLowerInvariant();
        string newContentEncoding = null;

        if (acceptEncoding.Contains("gzip"))
        {
            // gzip
            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
            newContentEncoding = "gzip";
        }
        else if (acceptEncoding.Contains("deflate"))
        {
            // deflate
            response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
            newContentEncoding = "deflate";
        }

        if (newContentEncoding != null)
        {
            response.AppendHeader("Content-Encoding", newContentEncoding);
            response.Cache.VaryByHeaders["Accept-Encoding"] = true;
        }
    }
}

The module is designed to work with IIS 7.0 or higher in integrated pipeline mode (Azure Websites have exactly this out of the box). That is the most widespread configuration, so generally it just works once you attach it. Please note that the module should be the first one in a list of modules.

Web.config registration sample:

<configuration>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="CdnHttpCompressionModule" preCondition="managedHandler" type="YourWebsite.Modules.CdnHttpCompressionModule, YourWebsite" />
      <!-- You may have other modules here -->
    </modules>  
  <system.webServer>
</configuration>

Upvotes: 0

Jportelas
Jportelas

Reputation: 646

Check these 2 articles, they might help you if you want to send compressed (gzip) content back to the clients:

http://christesene.com/mvc-3-action-filters-enable-page-compression-gzip/

http://www.west-wind.com/weblog/posts/2012/Apr/28/GZipDeflate-Compression-in-ASPNET-MVC

Upvotes: 0

Related Questions