From c257bbb74d6584d1640def883e011276e6da088b Mon Sep 17 00:00:00 2001 From: Elastic Jasper Date: Sat, 10 Sep 2016 09:22:22 -0400 Subject: [PATCH] Backport PR #8212 --------- **Commit 1:** [state/unhashUrl] use encode-uri-query to generate cleanly encoded urls By default, the url.format function stringifies the query object and encodes each parameter with `encodeURIComponent()`. This is effective, but does not match the native browser behavior, which is to only encode the non-`pchar` characters as defined by [rfc3986][1]. Because of this, angular's `$location.search()` function uses a function internally called `encodeUriQuery()` to mimic the browser behavior before updating `location.href`. To bring the same funtionality to the `unhashUrl()` function, the `encodeUriQuery()` was extracted into it's own package and used as the escape handler for `querystring.stringify()` [1]: https://www.ietf.org/rfc/rfc3986.txt * Original sha: d9dac3ffdcd5f7d963784e39e6c35b36b2d28cb6 * Authored by spalger on 2016-09-09T22:39:57Z --- package.json | 1 + .../state_management/state_hashing/unhash_url.js | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 6799048d8f82d..7d1427ef3e3a5 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "dragula": "3.7.0", "elasticsearch": "12.0.0-rc5", "elasticsearch-browser": "12.0.0-rc5", + "encode-uri-query": "1.0.0", "even-better": "7.0.2", "expiry-js": "0.1.7", "exports-loader": "0.6.2", diff --git a/src/ui/public/state_management/state_hashing/unhash_url.js b/src/ui/public/state_management/state_hashing/unhash_url.js index 3671b653dee22..34ad3982a0565 100644 --- a/src/ui/public/state_management/state_hashing/unhash_url.js +++ b/src/ui/public/state_management/state_hashing/unhash_url.js @@ -3,6 +3,12 @@ import { format as formatUrl, } from 'url'; +import encodeUriQuery from 'encode-uri-query'; + +import { + stringify as stringifyQueryString +} from 'querystring'; + import unhashQueryString from './unhash_query_string'; export default function unhashUrl(urlWithHashes, states) { @@ -26,11 +32,18 @@ export default function unhashUrl(urlWithHashes, states) { if (!appUrlParsed.query) return urlWithHashes; const appQueryWithoutHashes = unhashQueryString(appUrlParsed.query || {}, states); + + // encodeUriQuery implements the less-aggressive encoding done naturally by + // the browser. We use it to generate the same urls the browser would + const appQueryStringWithoutHashes = stringifyQueryString(appQueryWithoutHashes, null, null, { + encodeURIComponent: encodeUriQuery + }); + return formatUrl({ ...urlWithHashesParsed, hash: formatUrl({ pathname: appUrlParsed.pathname, - query: appQueryWithoutHashes, + search: appQueryStringWithoutHashes, }) }); }