« Previous Next »

Thread: IIS7: HTTP Compression failing

Last post 12-25-2008 5:09 PM by pajocomo. 0 replies.

Average Rating Rate It (5)

RSS

Page 1 of 1 (1 items)

Sort Posts:

  • 12-25-2008, 5:09 PM

    • pajocomo
    • Not Ranked
    • Joined on 02-11-2004, 12:34 PM
    • Portugal
    • Posts 9

    IIS7: HTTP Compression failing

    Hi all,

    I'm trying to build a reverse proxy, but I'm not getting HTTP compression working using IIS 7 on Win2008.

    Either using the compressed response from the remote server or using IIS's compression, I cannot make IE7 or Fiddler2 to accept the compressed content.

    Here is my code:

    global.asax.cs:

    namespace ReverseProxy
    {
        using System;
        using System.Collections.Generic;
        using System.Collections.Specialized;
        using System.IO;
        using System.Net;
        using System.Web;
    
        public class ReverseProxyHttpApplication : HttpApplication
        {
    
            #region Private Constants
    
            private const int BUFFER_SIZE = 65536;
            private const string StartsWithAppSettingsKey = "StartsWith";
            private const string ReplaceWithAppSettingsKey = "ReplaceWith";
    
            #endregion
    
            private static Dictionary<string, Action<HttpWebRequest, string>> setHeaders;
    
            private byte[] bytes = new byte[BUFFER_SIZE];
    
            public ReverseProxyHttpApplication()
            {
                ReverseProxyHttpApplication.setHeaders = new Dictionary<string, Action<HttpWebRequest, string>>(StringComparer.OrdinalIgnoreCase)
                {
    #if DEBUG
                    {"Accept-Encoding", (httpWebRequest, value) => { }},
    #endif
                    {"Accept", (httpWebRequest, value) => httpWebRequest.Accept = value},
                    {"Connection", null},
                    {"Content-Type", (httpWebRequest, value) => httpWebRequest.ContentType = value},
                    {"Content-Length", null},
                    {"Expect", null},
                    {"Date", null},
                    {"Host", null},
                    {"Referer", (httpWebRequest, value) => httpWebRequest.Referer = value},
                    {"TransferEncoding", (httpWebRequest, value) =>
                        {
                            httpWebRequest.SendChunked = true;
                            httpWebRequest.TransferEncoding = value;
                        }},
                    {"User-Agent", (httpWebRequest, value) => httpWebRequest.UserAgent = value}
                };
            }
    
            protected void Application_BeginRequest(object sender, EventArgs e)
            {
                string localPath = null;
                string remotePath;
                HttpContext context = this.Context;
    
                try
                {
                    HttpRequest request = this.Request;
                    HttpResponse response = this.Response;
    
                    localPath = request.AppRelativeCurrentExecutionFilePath;
    
                    remotePath = GetRemotePath(localPath);
    
                    if (string.IsNullOrEmpty(remotePath))
                    {
                        return;
                    }
    
                    HttpWebRequest httpWebRequest = SendRemoteRequest(remotePath, request);
    
                    GetRemoteResponse(response, httpWebRequest);
    
                    response.Flush();
                }
                finally
                {
                    this.CompleteRequest();
                }
            }
    
            private static string GetRemotePath(string localPath)
            {
                string remotePath;
    
                string startsWith = System.Web.Configuration.WebConfigurationManager.AppSettings[StartsWithAppSettingsKey];
    
                if (!localPath.StartsWith(startsWith, StringComparison.OrdinalIgnoreCase))
                {
                    return null;
                }
    
                remotePath = System.Web.Configuration.WebConfigurationManager.AppSettings[ReplaceWithAppSettingsKey] + localPath.Substring(startsWith.Length);
    
                return remotePath;
            }
    
            private HttpWebRequest SendRemoteRequest(string remotePath, HttpRequest request)
            {
                HttpWebRequest httpWebRequest;
    
                Uri remoteUri = new Uri(remotePath);
    
                httpWebRequest = (HttpWebRequest)(WebRequest.Create(remoteUri));
                httpWebRequest.Method = request.HttpMethod;
    
                SetRequestHeaders(httpWebRequest, request.Headers);
    
                SetRequestCookies(remoteUri, httpWebRequest, request.Cookies);
    
                if (request.ContentLength > 0)
                {
                    using (Stream requestStream = httpWebRequest.GetRequestStream())
                    {
                        this.CopyStream(request.InputStream, requestStream);
                    }
                }
    
                return httpWebRequest;
            }
    
            private void SetRequestHeaders(HttpWebRequest httpWebRequest, NameValueCollection requestHeaders)
            {
                WebHeaderCollection remoteRequestHeaders = httpWebRequest.Headers;
    
                foreach (string header in requestHeaders)
                {
                    string value = requestHeaders[header];
                    Action<HttpWebRequest, string> action;
                    if (ReverseProxyHttpApplication.setHeaders.TryGetValue(header, out action))
                    {
                        if (action != null)
                        {
                            action(httpWebRequest, value);
                        }
                    }
                    else
                    {
                        remoteRequestHeaders.Add(header, value);
                    }
                }
            }
    
            private static void SetRequestCookies(Uri remoteUri, HttpWebRequest httpWebRequest, HttpCookieCollection requestCookies)
            {
                if (requestCookies.Count > 0)
                {
                    httpWebRequest.CookieContainer = new CookieContainer();
    
                    foreach (string cookieName in requestCookies)
                    {
                        HttpCookie httpCookie = requestCookies[cookieName];
    
                        httpWebRequest.CookieContainer.Add(new Cookie
                        {
                            Name = cookieName,
                            Path = httpCookie.Path,
                            Domain = (string.IsNullOrEmpty(httpCookie.Domain)) ? remoteUri.Authority : httpCookie.Domain,
                            HttpOnly = httpCookie.HttpOnly,
                            Expires = httpCookie.Expires,
                            Secure = httpCookie.Secure
                        });
                    }
                }
            }
    
            private void GetRemoteResponse(HttpResponse response, HttpWebRequest httpWebRequest)
            {
                using (HttpWebResponse httpWebResponse = (HttpWebResponse)(httpWebRequest.GetResponse()))
                {
                    if (httpWebRequest.HaveResponse)
                    {
                        using (Stream remoteResponseStream = httpWebResponse.GetResponseStream())
                        {
                            this.CopyStream(remoteResponseStream, response.OutputStream);
                        }
    
                        SetResponseHeaders(response, httpWebResponse.Headers);
    
                        SetResponseCookies(response, httpWebResponse.Cookies);
                    }
                }
            }
    
            private static void SetResponseHeaders(HttpResponse response, WebHeaderCollection remoteResponseHeaders)
            {
                response.ClearHeaders();
    
                foreach (string header in remoteResponseHeaders)
                {
                    if ("Server".Equals(header, StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }
    
                    response.AppendHeader(header, remoteResponseHeaders[header]);
                }
            }
    
            private static void SetResponseCookies(HttpResponse response, CookieCollection responseCookies)
            {
                response.Cookies.Clear();
    
                foreach (Cookie cookie in responseCookies)
                {
                    response.Cookies.Add(new HttpCookie(cookie.Name, cookie.Value)
                    {
                        Path = cookie.Path,
                        Domain = cookie.Domain,
                        HttpOnly = cookie.HttpOnly,
                        Expires = cookie.Expires,
                        Secure = cookie.Secure
                    });
                }
            }
    
            private void CopyStream(Stream from, Stream to)
            {
                int read;
                while ((read = from.Read(this.bytes, 0, BUFFER_SIZE)) > 0)
                {
                    to.Write(this.bytes, 0, read);
                }
            }
        }
    }

    web.config:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
      <system.diagnostics>
        <assert assertuienabled="false" />
        <sources>
          <source name="ReverseProxy" switchValue="Verbose">
          </source>
        </sources>
      </system.diagnostics>
      <appSettings>
        <clear />
        <add key="StartsWith" value="~/" />
        <add key="ReplaceWith" value="http://msdn.microsoft.com/" />
      </appSettings>
      <system.web>
        <authentication mode="None" />
        <httpHandlers>
          <clear />
        </httpHandlers>
        <httpModules>
          <clear />
        </httpModules>
        <compilation debug="true" />
      </system.web>
      <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
        <handlers>
          <clear />
          <add name="dummy" path="*" verb="*" type="System.Web.HttpForbiddenHandler, System.Web" />
        </handlers>
        <modules>
        </modules>
      </system.webServer>
    </configuration>
    
    Paulo Morgado
    Portugal - Europe's West Coast
    http://PauloMorgado.NET/
Page 1 of 1 (1 items)