Javascript URL hackery

datchley

In one of the projects I have at work we have a number of environments that run the system (a web based application) – production, testing environments and development.  Each environment is assigned it’s own domain name. So for instance, our Systems Integration Testing (SIT) environment would be accessed as foo-sit.company.com.  The environment is always suffixed at the end of the system name in the URL with a ‘-’ dash.  The only time this is not the case is in production, where the URL would just be foo.company.com. This is pretty straight forward and an easy way to access multiple web application environments.

However, there are times when I want the application running in one environment to hit the database of another environment. For instance, when running reports that I’m coding in development, I want to run them against a more recent copy of the database in our SIT environment. Our backend PHP code allows this by accepting a ‘dbenv=ENV‘ POST parameter to tell it to use a different database environment than its default. So, I could have my development environment reports hit the SIT testing environment database by changing the URL to

http://foo-dev.company.com?dbenv=SIT

So, in our Javascript code in a number of these reports, we need to determine if the user is coming in wanting a different database environment than the default and pass the dbenv=ENV parameter ourself via the AJAX call to generate the report. Since we’re using Javascript and AJAX, this has to be dynamic as we build the parameters for the report dynamically as well. Here’s the snippet of code that does that in Javascript land, with the names changed to protect the innocent:

var o = {};
o = Ext.urlDecode((window.location.href.split('?',2))[1]);

if (!o.dbenv || !o) {
 var loc = /(?:foo(?:-([^\.]+)?)?)\.*/.exec(window.location.href);
 if (loc.length == 2) {
     o.dbenv = (loc[1]) ? loc[1].toUpperCase() : 'PROD';
 }
 else {
     o.dbenv = 'DEV';
 }
}
else {
 o.dbenv = o.dbenv.replace(/[^A-Za-z]+/,'');
}

var DBENV = o.dbenv;

Our team is using ExtJS as a cross-browser Javascript framework for our applications, so the ‘Ext.urlDecode()‘ call is the only non-plain Javascript portion of this code. It returns the decoded URL parameters in a Javascript object. Note that we’re only decoding the parameter portion of the URL here ('window.location.href.split('?',2))[1], since we’re just trying to determine if there is already a ‘dbenv=ENV‘ attached to it. Once we have the parameter portion of the URL as an object, we look to see if there is a ‘dbenv’ attribute on this object. If not, or if the object is undefined (no parameters were available to parse) we need to look at the URL itself and the suffix we talked about before to determine the database environment to pass. That’s where we see

var loc = /(?:foo(?:-([^\.]+)?)?)\.*/.exec(window.location.href);

Here, we take the URL itself, looking for the system name (in this case ‘foo’) followed by a ‘-’ dash and some optional text which we hope to be the environment name in lower case (‘-dev’, ‘-sit’, etc.). Line 4 gives us back an array from the regular expression. This array will always have at least 1 element, which is the part of the URL that matched the pattern entirely, accessible via loc[0] at this point. If we matched a database environment, it will be in loc[1], the second element of the array.

The time when this is NOT true, is in production, which has no ‘-env’ suffix on the URL – in which case loc[1] will be ‘undefined’. In the code, I’ve never tested any occurrence when loc has a length of less than 2 (since in our regex match if there is no suffix, we always get ‘undefined’ back because of the capturing parenthesis). But, in case some weird URL rewriting happens because of our web server admins (and they do change things without telling us sometimes) we have a simple check and if we don’t get a length of 2, we simply default the database environment to DEV.

Otherwise, we set the database environment to whatever was matched in the suffix, uppercased or ‘PROD’ if it was undefined. This is fairly straight forward and has worked for us so far. But, if you’ve got other ideas or suggestions, I’d love to hear them in the comments.

Enjoy!


Leave a Reply