fix(router): encode URLs the same way AngularJS did (closer to spec) (#17890)

fixes #16067
This commit is contained in:
Jason Aden 2017-07-06 17:10:25 -07:00 committed by GitHub
parent c69fff15c9
commit ae27af7399
3 changed files with 34 additions and 2 deletions

View File

@ -325,8 +325,24 @@ function serializeSegment(segment: UrlSegmentGroup, root: boolean): string {
}
}
/**
* This method is intended for encoding *key* or *value* parts of query component. We need a custom
* method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
* encoded per http://tools.ietf.org/html/rfc3986:
* query = *( pchar / "/" / "?" )
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* pct-encoded = "%" HEXDIG HEXDIG
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*/
export function encode(s: string): string {
return encodeURIComponent(s);
return encodeURIComponent(s)
.replace(/%40/g, '@')
.replace(/%3A/gi, ':')
.replace(/%24/g, '$')
.replace(/%2C/gi, ',')
.replace(/%3B/gi, ';');
}
export function decode(s: string): string {

View File

@ -219,6 +219,22 @@ describe('url serializer', () => {
expect(url.serialize(tree)).toEqual(u);
});
it('should encode query params leaving sub-delimiters intact', () => {
const percentChars = '/?#[]&+= ';
const percentCharsEncoded = '%2F%3F%23%5B%5D%26%2B%3D%20';
const intactChars = '!$\'()*,;:';
const params = percentChars + intactChars;
const paramsEncoded = percentCharsEncoded + intactChars;
const mixedCaseString = 'sTrInG';
expect(percentCharsEncoded).toEqual(encode(percentChars));
expect(intactChars).toEqual(encode(intactChars));
// Verify it replaces repeated characters correctly
expect(paramsEncoded + paramsEncoded).toEqual(encode(params + params));
// Verify it doesn't change the case of alpha characters
expect(mixedCaseString + paramsEncoded).toEqual(encode(mixedCaseString + params));
});
it('should encode/decode fragment', () => {
const u = `/one#${encodeURI("one two=three four")}`;
const tree = url.parse(u);

View File

@ -71,6 +71,6 @@ export function setUpLocationSync(ngUpgrade: UpgradeModule) {
ngUpgrade.$injector.get('$rootScope')
.$on('$locationChangeStart', (_: any, next: string, __: string) => {
url.href = next;
router.navigateByUrl(url.pathname + url.search);
router.navigateByUrl(url.pathname + url.search + url.hash);
});
}