fix(router): encode URLs the same way AngularJS did (closer to spec) (#17890)
fixes #16067
This commit is contained in:
parent
c69fff15c9
commit
ae27af7399
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user