fix(Router): handling of special chars in dynamic segments

Closes #7804
This commit is contained in:
Victor Berchet 2016-03-28 18:07:12 -07:00
parent 1c20a62611
commit 0bcfcde63d
2 changed files with 69 additions and 2 deletions

View File

@ -62,7 +62,7 @@ class DynamicPathSegment implements PathSegment {
throw new BaseException( throw new BaseException(
`Route generator for '${this.name}' was not included in parameters passed.`); `Route generator for '${this.name}' was not included in parameters passed.`);
} }
return normalizeString(params.get(this.name)); return encodeDynamicSegment(normalizeString(params.get(this.name)));
} }
} }
@ -130,7 +130,7 @@ export class ParamRoutePath implements RoutePath {
captured.push(currentUrlSegment.path); captured.push(currentUrlSegment.path);
if (pathSegment instanceof DynamicPathSegment) { if (pathSegment instanceof DynamicPathSegment) {
positionalParams[pathSegment.name] = currentUrlSegment.path; positionalParams[pathSegment.name] = decodeDynamicSegment(currentUrlSegment.path);
} else if (!pathSegment.match(currentUrlSegment.path)) { } else if (!pathSegment.match(currentUrlSegment.path)) {
return null; return null;
} }
@ -269,3 +269,43 @@ export class ParamRoutePath implements RoutePath {
} }
static RESERVED_CHARS = RegExpWrapper.create('//|\\(|\\)|;|\\?|='); static RESERVED_CHARS = RegExpWrapper.create('//|\\(|\\)|;|\\?|=');
} }
let REGEXP_PERCENT = /%/g;
let REGEXP_SLASH = /\//g;
let REGEXP_OPEN_PARENT = /\(/g;
let REGEXP_CLOSE_PARENT = /\)/g;
let REGEXP_SEMICOLON = /;/g;
function encodeDynamicSegment(value: string): string {
if (isBlank(value)) {
return null;
}
value = StringWrapper.replaceAll(value, REGEXP_PERCENT, '%25');
value = StringWrapper.replaceAll(value, REGEXP_SLASH, '%2F');
value = StringWrapper.replaceAll(value, REGEXP_OPEN_PARENT, '%28');
value = StringWrapper.replaceAll(value, REGEXP_CLOSE_PARENT, '%29');
value = StringWrapper.replaceAll(value, REGEXP_SEMICOLON, '%3B');
return value;
}
let REGEXP_ENC_SEMICOLON = /%3B/ig;
let REGEXP_ENC_CLOSE_PARENT = /%29/ig;
let REGEXP_ENC_OPEN_PARENT = /%28/ig;
let REGEXP_ENC_SLASH = /%2F/ig;
let REGEXP_ENC_PERCENT = /%25/ig;
function decodeDynamicSegment(value: string): string {
if (isBlank(value)) {
return null;
}
value = StringWrapper.replaceAll(value, REGEXP_ENC_SEMICOLON, ';');
value = StringWrapper.replaceAll(value, REGEXP_ENC_CLOSE_PARENT, ')');
value = StringWrapper.replaceAll(value, REGEXP_ENC_OPEN_PARENT, '(');
value = StringWrapper.replaceAll(value, REGEXP_ENC_SLASH, '/');
value = StringWrapper.replaceAll(value, REGEXP_ENC_PERCENT, '%');
return value;
}

View File

@ -50,6 +50,33 @@ export function main() {
}); });
}); });
describe('dynamic segments', () => {
it('should parse parameters', () => {
var rec = new ParamRoutePath('/test/:id');
var url = new Url('test', new Url('abc'));
var match = rec.matchUrl(url);
expect(match.allParams).toEqual({'id': 'abc'});
});
it('should decode special characters when parsing', () => {
var rec = new ParamRoutePath('/test/:id');
var url = new Url('test', new Url('abc%25%2F%2f%28%29%3B'));
var match = rec.matchUrl(url);
expect(match.allParams).toEqual({'id': 'abc%//();'});
});
it('should generate url', () => {
var rec = new ParamRoutePath('/test/:id');
expect(rec.generateUrl({'id': 'abc'}).urlPath).toEqual('test/abc');
});
it('should encode special characters when generating', () => {
var rec = new ParamRoutePath('/test/:id');
expect(rec.generateUrl({'id': 'abc/def/%();'}).urlPath)
.toEqual('test/abc%2Fdef%2F%25%28%29%3B');
});
});
describe('matrix params', () => { describe('matrix params', () => {
it('should be parsed along with dynamic paths', () => { it('should be parsed along with dynamic paths', () => {
var rec = new ParamRoutePath('/hello/:id'); var rec = new ParamRoutePath('/hello/:id');