Skip to content

Commit

Permalink
Separated the URL parsing.
Browse files Browse the repository at this point in the history
This is intrinsically linked to the route parsing, but it shouldn't
really be in the same place.
  • Loading branch information
EdJ committed Jun 12, 2013
1 parent 26c65ce commit 0fa47b6
Show file tree
Hide file tree
Showing 2 changed files with 264 additions and 0 deletions.
70 changes: 70 additions & 0 deletions Routes/urlParser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
var qs = require('querystring');

module.exports = (function() {
var isStaticUrl = function (statics, pathWithQueryString) {
if (! ~pathWithQueryString.indexOf('.') || !! ~pathWithQueryString.indexOf('?')) {
return false;
}

for (var i = statics.length; i--; ) {
var st = pathWithQueryString.indexOf(statics[i]);
if (!st) {
return true;
}
}

return false;
};

var parseParameters = function (patterns, pathWithQs) {
var split = pathWithQs.split('?');
if (!split.length) {
return {};
}


var path = split[0];
if (path.substr(-1) != '/') {
path += '/';
}

var queryStringData = qs.parse(split[1] || '');
var pattern;
var output;

for (var i = patterns.length; i--; ) {
pattern = patterns[i];
fn = pattern.func;

output = fn(path);
if (!output) {
continue;
}

Utils.extend(output, pattern.data);
Utils.extend(output, queryStringData);

output._isStatic = false;
return output;
}

return {};
};

var UrlParser = function (routes, statics, pathWithQueryString) {
var isStatic = isStaticUrl(statics, pathWithQueryString);
if (isStatic) {
return {
_isStatic: true
};
}

return parseParameters(routes, pathWithQueryString);
};

// Expose some functions for unit testing.
UrlParser.isStaticUrl = isStaticUrl;
UrlParser.parseParameters = parseParameters;

return UrlParser;
})();
194 changes: 194 additions & 0 deletions test/Routes/urlParser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// This is heplful for some of the tests.
Utils = require('../../Utilities/utils');

describe('UrlParser', function() {
var urlParser;
beforeEach(function() {
urlParser = require('../../Routes/urlParser');
});

describe('isStaticUrl', function() {
it('should return false if the URL is dynamic.', function() {
var result = urlParser.isStaticUrl(['/test'], '/test.html?test=1');

result.should.be.false;
});

it('should return false if the URL is not a file.', function() {
var result = urlParser.isStaticUrl(['/test'], '/test/test2');

result.should.be.false;
});

it('should return true if the URL matches a static path.', function() {
var result = urlParser.isStaticUrl(['/test'], '/test/test2.js');

result.should.be.true;
});

it('should return true if the URL matches one of many static paths.', function() {
var result = urlParser.isStaticUrl(['/test', '/tes', '/t', '/hello', '/content'], '/test/test2.js');

result.should.be.true;
});

it('should return false if the URL matches a static path not at the root level.', function() {
var result = urlParser.isStaticUrl(['/test'], '/hello/test/test2.js');

result.should.be.false;
});
});

describe('#parseParameters()', function() {
it('should return an empty object for a blank URL.', function() {
var result = urlParser.parseParameters([], '');

result.should.eql({});
});

it('should return an empty object when no route matches.', function() {
var result = urlParser.parseParameters([], '/test');

result.should.eql({});
});

it('should gain parameters based on the matched route\'s additional parameters.', function() {
var routeFunction = function() {
return {};
};

var routeData = {
someData: 'yes'
};

var result = urlParser.parseParameters([{
func: routeFunction,
data: routeData
}
], '/');

result.should.eql({
someData: 'yes',
_isStatic: false
});
});

it('should gain parameters from the query string.', function() {
var routeFunction = function() {
return {};
};

var routeData = {};

var result = urlParser.parseParameters([{
func: routeFunction,
data: routeData
}
], '/?testData=test');

result.should.eql({
testData: 'test',
_isStatic: false
});
});

it('should override default parameters with query string parameters.', function() {
var routeFunction = function() {
return {};
};

var routeData = {
testData: 'original data.'
};

var result = urlParser.parseParameters([{
func: routeFunction,
data: routeData
}
], '/?testData=test');

result.should.eql({
testData: 'test',
_isStatic: false
});
});

it('should only gain parameters from a matching route.', function() {
var routeFunction = function() {
return {};
};

var failedRouteFunction = function() {
return false;
};

var routeData = {
testData: 'original data.'
};

var failedRouteData = {
otherTestData: 'original failed route data.'
};

var result = urlParser.parseParameters([{
func: failedRouteFunction,
data: failedRouteData
}, {
func: routeFunction,
data: routeData
}, {
func: failedRouteFunction,
data: failedRouteData
}
], '/test');

result.should.eql({
testData: 'original data.',
_isStatic: false
});
});
});

describe('public interface', function() {
it('should return an object with only the _isStatic property if the URL matches a static path.', function() {
var path = urlParser([], ['/test'], '/test/test.html');

path.should.eql({
_isStatic: true
});
});

it('should ignore matching routes if a static path is available.', function() {
var path = urlParser([{
func: function() {
return {};
},
data: {
test: 'data'
}
}
], ['/test'], '/test/test.html');

path.should.eql({
_isStatic: true
});
});

it('should use a route if no static path matches.', function() {
var path = urlParser([{
func: function() {
return {};
},
data: {
test: 'data'
}
}
], ['/Content'], '/test/test.html');

path.should.eql({
test: 'data',
_isStatic: false
});
});
});
});

0 comments on commit 0fa47b6

Please sign in to comment.