Skip to content

Commit 27b87ef

Browse files
committed
fix(router): throw when cannot parse a url
1 parent 44709e0 commit 27b87ef

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

modules/@angular/router/src/url_tree.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ function matchUrlQueryParamValue(str: string): string {
277277
}
278278

279279
class UrlParser {
280-
constructor(private remaining: string) {}
280+
private remaining: string;
281+
constructor(private url: string) { this.remaining = url; }
281282

282283
peekStartsWith(str: string): boolean { return this.remaining.startsWith(str); }
283284

@@ -422,7 +423,16 @@ class UrlParser {
422423
const segments: {[key: string]: UrlSegment} = {};
423424
this.capture('(');
424425
while (!this.peekStartsWith(')') && this.remaining.length > 0) {
425-
let path = matchPathWithParams(this.remaining);
426+
const path = matchPathWithParams(this.remaining);
427+
428+
const next = this.remaining[path.length];
429+
430+
// if is is not one of these characters, then the segment was unescaped
431+
// or the group was not closed
432+
if (next !== '/' && next !== ')' && next !== ';') {
433+
throw new Error(`Cannot parse url '${this.url}'`);
434+
}
435+
426436
let outletName: string;
427437
if (path.indexOf(':') > -1) {
428438
outletName = path.substr(0, path.indexOf(':'));
@@ -435,7 +445,6 @@ class UrlParser {
435445
const children = this.parseSegmentChildren();
436446
segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] :
437447
new UrlSegment([], children);
438-
439448
if (this.peekStartsWith('//')) {
440449
this.capture('//');
441450
}

modules/@angular/router/test/url_serializer.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ describe('url serializer', () => {
148148
expect(url.serialize(tree)).toEqual('/one#two');
149149
});
150150

151+
151152
it('should parse empty fragment', () => {
152153
const tree = url.parse('/one#');
153154
expect(tree.fragment).toEqual('');
@@ -183,6 +184,17 @@ describe('url serializer', () => {
183184
expect(url.serialize(tree)).toEqual(u);
184185
});
185186
});
187+
188+
describe('error handling', () => {
189+
it('should throw when invalid characters inside children', () => {
190+
expect(() => url.parse('/one/(left#one)'))
191+
.toThrowError('Cannot parse url \'/one/(left#one)\'');
192+
});
193+
194+
it('should throw when missing closing )', () => {
195+
expect(() => url.parse('/one/(left')).toThrowError('Cannot parse url \'/one/(left\'');
196+
});
197+
});
186198
});
187199

188200
function expectSegment(segment: UrlSegment, expected: string, hasChildren: boolean = false): void {

0 commit comments

Comments
 (0)