2017-05-04 15:20:41 +00:00
|
|
|
/* @flow */
|
|
|
|
|
2021-06-02 19:21:39 +00:00
|
|
|
import Bourne from '@hapi/bourne';
|
|
|
|
|
2020-05-07 22:26:37 +00:00
|
|
|
import { reportError } from './helpers';
|
2018-07-21 15:16:32 +00:00
|
|
|
|
2021-06-02 19:21:39 +00:00
|
|
|
/**
|
|
|
|
* A list if keys to ignore when parsing.
|
2021-11-04 21:10:43 +00:00
|
|
|
*
|
2021-06-02 19:21:39 +00:00
|
|
|
* @type {string[]}
|
|
|
|
*/
|
|
|
|
const blacklist = [ '__proto__', 'constructor', 'prototype' ];
|
|
|
|
|
2017-05-04 15:20:41 +00:00
|
|
|
/**
|
2017-07-27 18:50:09 +00:00
|
|
|
* Parses the query/search or fragment/hash parameters out of a specific URL and
|
|
|
|
* returns them as a JS object.
|
2017-05-04 15:20:41 +00:00
|
|
|
*
|
2020-05-07 22:26:37 +00:00
|
|
|
* @param {URL} url - The URL to parse.
|
2017-07-27 18:50:09 +00:00
|
|
|
* @param {boolean} dontParse - If falsy, some transformations (for parsing the
|
|
|
|
* value as JSON) will be executed.
|
|
|
|
* @param {string} source - If {@code 'search'}, the parameters will parsed out
|
|
|
|
* of {@code url.search}; otherwise, out of {@code url.hash}.
|
2017-05-04 15:20:41 +00:00
|
|
|
* @returns {Object}
|
|
|
|
*/
|
2020-05-07 22:26:37 +00:00
|
|
|
export function parseURLParams(
|
2022-06-18 19:23:40 +00:00
|
|
|
url: URL | string,
|
2017-05-04 15:20:41 +00:00
|
|
|
dontParse: boolean = false,
|
|
|
|
source: string = 'hash'): Object {
|
2022-06-18 19:23:40 +00:00
|
|
|
if (typeof url === 'string') {
|
|
|
|
// eslint-disable-next-line no-param-reassign
|
|
|
|
url = new URL(url);
|
|
|
|
}
|
2017-05-04 15:20:41 +00:00
|
|
|
const paramStr = source === 'search' ? url.search : url.hash;
|
|
|
|
const params = {};
|
2019-02-21 23:30:02 +00:00
|
|
|
const paramParts = (paramStr && paramStr.substr(1).split('&')) || [];
|
2017-05-04 15:20:41 +00:00
|
|
|
|
2019-02-21 23:30:02 +00:00
|
|
|
// Detect and ignore hash params for hash routers.
|
|
|
|
if (source === 'hash' && paramParts.length === 1) {
|
|
|
|
const firstParam = paramParts[0];
|
|
|
|
|
|
|
|
if (firstParam.startsWith('/') && firstParam.split('&').length === 1) {
|
|
|
|
return params;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
paramParts.forEach(part => {
|
2017-05-04 15:20:41 +00:00
|
|
|
const param = part.split('=');
|
|
|
|
const key = param[0];
|
|
|
|
|
2021-06-16 18:53:26 +00:00
|
|
|
if (!key || key.split('.').some(k => blacklist.includes(k))) {
|
2017-05-04 15:20:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let value;
|
|
|
|
|
|
|
|
try {
|
|
|
|
value = param[1];
|
2019-07-08 22:10:18 +00:00
|
|
|
|
2017-05-04 15:20:41 +00:00
|
|
|
if (!dontParse) {
|
2019-07-08 22:10:18 +00:00
|
|
|
const decoded = decodeURIComponent(value).replace(/\\&/, '&');
|
|
|
|
|
2021-06-02 19:21:39 +00:00
|
|
|
value = decoded === 'undefined' ? undefined : Bourne.parse(decoded);
|
2017-05-04 15:20:41 +00:00
|
|
|
}
|
|
|
|
} catch (e) {
|
2018-07-21 15:16:32 +00:00
|
|
|
reportError(
|
|
|
|
e, `Failed to parse URL parameter value: ${String(value)}`);
|
2017-05-04 15:20:41 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
params[key] = value;
|
|
|
|
});
|
|
|
|
|
|
|
|
return params;
|
|
|
|
}
|