From 27b87ef53576e0db55af393645aeee043cd6bdf7 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Thu, 21 Jul 2016 15:58:21 -0700 Subject: [PATCH] fix(router): throw when cannot parse a url --- modules/@angular/router/src/url_tree.ts | 15 ++++++++++++--- .../@angular/router/test/url_serializer.spec.ts | 12 ++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/modules/@angular/router/src/url_tree.ts b/modules/@angular/router/src/url_tree.ts index 965fc8cb78..175d96c756 100644 --- a/modules/@angular/router/src/url_tree.ts +++ b/modules/@angular/router/src/url_tree.ts @@ -277,7 +277,8 @@ function matchUrlQueryParamValue(str: string): string { } class UrlParser { - constructor(private remaining: string) {} + private remaining: string; + constructor(private url: string) { this.remaining = url; } peekStartsWith(str: string): boolean { return this.remaining.startsWith(str); } @@ -422,7 +423,16 @@ class UrlParser { const segments: {[key: string]: UrlSegment} = {}; this.capture('('); while (!this.peekStartsWith(')') && this.remaining.length > 0) { - let path = matchPathWithParams(this.remaining); + const path = matchPathWithParams(this.remaining); + + const next = this.remaining[path.length]; + + // if is is not one of these characters, then the segment was unescaped + // or the group was not closed + if (next !== '/' && next !== ')' && next !== ';') { + throw new Error(`Cannot parse url '${this.url}'`); + } + let outletName: string; if (path.indexOf(':') > -1) { outletName = path.substr(0, path.indexOf(':')); @@ -435,7 +445,6 @@ class UrlParser { const children = this.parseSegmentChildren(); segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] : new UrlSegment([], children); - if (this.peekStartsWith('//')) { this.capture('//'); } diff --git a/modules/@angular/router/test/url_serializer.spec.ts b/modules/@angular/router/test/url_serializer.spec.ts index 59ed286804..abed0dd90b 100644 --- a/modules/@angular/router/test/url_serializer.spec.ts +++ b/modules/@angular/router/test/url_serializer.spec.ts @@ -148,6 +148,7 @@ describe('url serializer', () => { expect(url.serialize(tree)).toEqual('/one#two'); }); + it('should parse empty fragment', () => { const tree = url.parse('/one#'); expect(tree.fragment).toEqual(''); @@ -183,6 +184,17 @@ describe('url serializer', () => { expect(url.serialize(tree)).toEqual(u); }); }); + + describe('error handling', () => { + it('should throw when invalid characters inside children', () => { + expect(() => url.parse('/one/(left#one)')) + .toThrowError('Cannot parse url \'/one/(left#one)\''); + }); + + it('should throw when missing closing )', () => { + expect(() => url.parse('/one/(left')).toThrowError('Cannot parse url \'/one/(left\''); + }); + }); }); function expectSegment(segment: UrlSegment, expected: string, hasChildren: boolean = false): void {