Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 68 additions & 17 deletions lib/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ exports = module.exports = internals.Route = function (options, server) {

Utils.assert(this.constructor === internals.Route, 'Route must be instantiated using new');
Utils.assert(settings.path, 'Route options missing path');
Utils.assert(settings.path.match(internals.Route.pathRegex), 'Invalid path: ' + settings.path);
Utils.assert(settings.path.match(internals.Route.validatePathRegex), 'Invalid path: ' + settings.path);
Utils.assert(settings.method, 'Route options missing method');

this.server = server;
Expand Down Expand Up @@ -110,8 +110,20 @@ exports = module.exports = internals.Route = function (options, server) {
};


// / legal-characters percent-encoded param /param?
internals.Route.pathRegex = /^\/|((\/(([\w\!\$&'\(\)\*\+\,;\=\:@\-\.~]|%[A-F0-9]{2})+|(\{\w+\})))+(\/(\{\w+\?\})?)?)$/;
/*
/path/{param}/path/{param?}
/path/{param*2}/path
/path/{param*2}
/{param*}
*/

// |--/-| |------------------------------------------/segment/segment/.../{param?}----------------------------------------------|
// . . . |-------------------------------/segments-----------------------------------||-------/optional-param--------------| .
// . . . . |---------------------------segment-content----------------------------| .. |--------{param*|?}-------------| . .
// . . . . .|----------------path-characters--------------| . .. |------decorators-----| . . .
// . . . . ..|-------legal-characters------| |--%encode-| . |-------{param}------|. .. |-----*n------| |?-| . . .
internals.Route.validatePathRegex = /(^\/$)|(^(\/(([\w\!\$&'\(\)\*\+\,;\=\:@\-\.~]|%[A-F0-9]{2})+|(\{\w+(\*[1-9]\d*)?\})))*(\/(\{\w+((\*([1-9]\d*)?)|(\?))?\})?)?$)/;
// a a b c de f f e g h h gdc i j kl m m l n nk j i b


internals.Route.prototype._generateRegex = function () {
Expand All @@ -125,37 +137,76 @@ internals.Route.prototype._generateRegex = function () {
var pathRX = '';
var fingerprint = '';

var paramRegex = /^\{(\w+)(?:(\*)(\d+)?)?(\?)?\}$/; // $1: name, $2: *, $3: segments, $4: optional

for (var i = 1, il = segments.length; i < il; ++i) { // Skip first empty segment
var segment = segments[i];

if (segment.charAt(0) === '{') {
var param = segment.match(paramRegex);
if (param) {

// Parameter

var isOptional = segment.charAt(segment.length - 2) === '?';
var name = segment.slice(1, isOptional ? -2 : -1); // Drop {} and ?
var name = param[1];
var isMulti = !!param[2];
var multiCount = param[3] && parseInt(param[3], 10);
var isOptional = !!param[4];

Utils.assert(!params[name], 'Cannot repeat the same parameter name');
params[name] = true;
pathRX += (trailingSlashOptional ? '(?:' : '') + '\\/([^\\/]+)' + (trailingSlashOptional ? ')' : '') + (isOptional ? '?' : '');
fingerprint += '/?';

var segmentRX = (!isMulti ? '\\/([^\\/]+)' : '((?:\\/(?:[^\\/]+))' + (multiCount ? '{' + multiCount + '}' : '*') + ')');
if (isOptional) {
if (trailingSlashOptional) {
pathRX += '(?:(?:\\/)|(?:' + segmentRX + '))?'
}
else {
pathRX += '(?:(?:\\/)|(?:' + segmentRX + '))';
}
}
else {
pathRX += segmentRX;
}

if (isMulti) {
if (multiCount) {
for (var m = 0; m < multiCount; ++m) {
fingerprint += '/?';
}
}
else {
fingerprint += '/?*';
}
}
else {
fingerprint += '/?';
}
}
else {

// Literal

pathRX += '\\/' + Utils.escapeRegex(segment);
fingerprint += '/' + segment;
if (segment) {
pathRX += '\\/' + Utils.escapeRegex(segment);
fingerprint += '/' + segment;
}
else {
pathRX += '\\/';
if (trailingSlashOptional) {
pathRX += '?';
}

fingerprint += '/';
}
}
}

// Trailing /

if (this.path.charAt(this.path.length - 1) === '/') {
pathRX += '\\/' + (trailingSlashOptional ? '?' : '');
fingerprint += '/';
if (this.server.settings.router.isCaseSensitive) {
this.regexp = new RegExp('^' + pathRX + '$');
}
else {
this.regexp = new RegExp('^' + pathRX + '$', 'i');
}

this.regexp = new RegExp('^' + pathRX + '$', this.server.settings.router.isCaseSensitive ? '' : 'i');
this.params = Object.keys(params);
this.fingerprint = fingerprint;
};
Expand Down
Loading