diff --git a/package.json b/package.json index da8b2fce9b95a..b45cee85d7c22 100644 --- a/package.json +++ b/package.json @@ -94,6 +94,7 @@ "d3": "3.5.6", "elasticsearch": "8.0.1", "elasticsearch-browser": "8.0.1", + "encode-uri-query": "1.0.0", "expiry-js": "0.1.7", "exports-loader": "0.6.2", "expose-loader": "0.7.0", 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, }) }); }