Simple Cross Domain HttpHandler proxy

I recently ran into the problem where I needed to forward cookies to a WCF service running on a different port to the originating request. This caused all sorts of cross domain issues between browsers.

In the end I settled on using a IHttpHandler to forward the requests and figure this might be useful to others.

public class MagicProxy : IHttpHandler
{
    private const int WCFServicePort = 8081;
    private const string WCFServiceDomain = "localhost";
    /// <summary>
    /// Method calls when client request the server
    /// </summary>
    /// <param name="context">HTTP context for client</param>
    public void ProcessRequest(HttpContext context)
    {

        Tuple<bool, string> requestURL = BuildRequestURI(context); //all site accepted

        if (requestURL.Item1)
        {
            //create the web request to get the remote stream
            HttpWebRequest forwardRequest = (HttpWebRequest)WebRequest.Create(requestURL.Item2);

            HttpWebResponse response;

            try
            {
                forwardRequest.Method = context.Request.HttpMethod;

                foreach (string item in context.Request.Cookies)
                {
                    HttpCookie OriginalCookie = context.Request.Cookies[item];
                    forwardRequest.CookieContainer = new CookieContainer();
                    forwardRequest.CookieContainer.Add(new Cookie(OriginalCookie.Name, OriginalCookie.Value, OriginalCookie.Path, WCFServiceDomain)); 
                }

                SetHeaders(context.Request.Headers, forwardRequest);

                if (forwardRequest.Method.ToLower() == "post")
                    context.Request.GetBufferlessInputStream().CopyTo(forwardRequest.GetRequestStream());

                response = (HttpWebResponse) forwardRequest.GetResponse();
            }
            catch (System.Net.WebException we)
            {
                //remote url not found, send 404 to client 
                context.Response.StatusCode = 404;
                context.Response.StatusDescription = "Not Found";
                context.Response.Write("<h2>Page not found</h2>");
                context.Response.End();
                return;
            }

            response.GetResponseStream().CopyTo(context.Response.OutputStream);

            //close streams
            response.Close();   
        }

        context.Response.End();
    }

    public void SetHeaders(NameValueCollection originalRequest, HttpWebRequest forwardRequest)
    {
        string connection = originalRequest["Connection"];
        int contentLength = string.IsNullOrEmpty(originalRequest["Content-Length"]) ? 0 : int.Parse(originalRequest["Content-Length"]);
        string contentType = originalRequest["Content-Type"];
        string accept = originalRequest["Accept"];
        string host = originalRequest["Host"];
        string referer = originalRequest["Referer"];
        string useragent = originalRequest["User-Agent"];

        forwardRequest.KeepAlive = connection.ToLower() == "keep-alive";
        forwardRequest.ContentLength = contentLength;
        forwardRequest.ContentType = contentType;
        forwardRequest.Accept = accept;
        forwardRequest.Host = host;
        forwardRequest.Referer = referer;
        forwardRequest.UserAgent = useragent;

        string pragma = originalRequest["Pragma"];
        string acceptEncoding = originalRequest["Accept-Encoding"];
        string xRequestedWith = originalRequest["X-Requested-With"];
        string dnt = originalRequest["DNT"];

        if (!string.IsNullOrEmpty(pragma))
            forwardRequest.Headers.Add("Pragma", pragma);

        if (!string.IsNullOrEmpty(acceptEncoding))
            forwardRequest.Headers.Add("Accept-Encoding", acceptEncoding);

        if (!string.IsNullOrEmpty(xRequestedWith))
            forwardRequest.Headers.Add("X-Requested-With", xRequestedWith);

        if (!string.IsNullOrEmpty(dnt))
            forwardRequest.Headers.Add("DNT", dnt);

    }

    public Tuple<bool, string> BuildRequestURI(HttpContext context)
    {
        string serviceName = context.Request.QueryString["ServiceName"];
        string serviceMethod = context.Request.QueryString["ServiceMethod"];

        if (!string.IsNullOrEmpty(serviceName) && !string.IsNullOrEmpty(serviceMethod))
        {
            return new Tuple<bool, string>(true, string.Format("http://{0}:{1}/{2}/{3}", WCFServiceDomain, WCFServicePort, serviceName, serviceMethod));
        }
        else
        {
            return new Tuple<bool, string>(false, null);
        }            
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}
Advertisements

JSLinq Sum method

JSLINQ is an awesome library that attempts to mimic the functionality provided by .NET LINQ libraries in clientside javascript code.

However while it is a great implementation it lacks a Sum method so for anyone interested here is the Sum method for JSLINQ that I created…

Sum: function (clause) {
    var values = this.Select(clause).ToArray();

    if (values != null) {
        var result = 0;

        for (var i = 0; i < values.length; i++) {
            var val = values[i];
            if (!isNaN(parseFloat(val)) && isFinite(val)) {
                result = result + parseInt(val);
            }
        }

        return result;
    } else {
        throw new Error("Argument Null Source");
    }
}