This post is over 6 months old. Some details, especially technical, may have changed.

JavaScript Proxy Pattern

More often than not when using 3rd party Javascript widgets/plugins/frameworks is that they don't behave in exactly the way that you want forcing you to change tactics, write some horribly messy boilerplate code, hack the original code or look for alternatives. The proxy pattern is a useful pattern that provides a sort of AOP-lite technique that can be used to transparently manage 3rd party code without having to make breaking changes or repeating horrible code from a single point in the code.

Functions are 1st class objects in JavaScript and this is the feature that powers this pattern. Imagine the setup below,

// AJAX Object
var XHR = {
    get : function(url, callback){
        // perform ajax call to url
        // call the callbakc with the returned data
    }
}

// specific internal ajax functions.  
// These are 3rd party code that shouldn't be touched
function GetData(url, callback){
    XHR.get(url, function(data){
        var parsedData = parse(data);
        callback(parsedData);
    });
}

function GetData2(url, callback){ /* similar thing to GetData*/ }
...
function GetDataN(url, callback){ /* similar thing to GetData*/ }

Now imagine there are a set of URLs that require some sort of authentication token passed along with the request. How do we deal with that? Well some people would just hack the internal functions but that's a bad idea as it probably breaks other parts of the system. Another way to do it would be to write your own Ajax framework for the new calls you want to make but that's overkill. The proxy pattern can help here.

// THE PROXY BLOCK
(function(){

    // create empty list of secured URLs
    XHR.securedURLs = [];

    // point to original function
    var _get = XHR.get;

    // create proxy function
    XHR.get = function(url, callback){
        // is url a secured url?
        if(XHR.securedURLs.indexOf(url) > -1){
            // append authentication token
            url += "?authToken=" + XHR.token;
        }

        // call original get function with potentially updated url
        _get(url, callback);
    }
})();

XHR.token = "AUTH_TOKEN";
XHR.securedURLs.push("https://secured.kainos.com");

GetData("https://secured.kainos.com", function(d){ /* code */ } );  // via proxy
GetData("http://notsecured.kainos.com", function(d){ /* code */ } );  // via original

So basically if the URL is a secured URL (present in the XHR.securedURLs array) then there will be a bit of pre-processing done to the URL before the function is called. Otherwise the normal function is called. That is the primary aim of the proxy pattern - to enhance existing functionality - at the very least the proxied function should fall back to the original function otherwise other parts of the system could be come affected (unless you know what you are doing of course - cancelling illegal calls etc).

Published in JavaScript on October 18, 2010