Skip to content

Instantly share code, notes, and snippets.

@DimitrK
Last active December 31, 2020 20:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DimitrK/ece75318efbfce2605bfcf1a035f1472 to your computer and use it in GitHub Desktop.
Save DimitrK/ece75318efbfce2605bfcf1a035f1472 to your computer and use it in GitHub Desktop.
Similar to URLSearchParams. Manipulate URL GET parameters. On `toString` sorts URL parameters by variable name in order to improve SEO when you use the generated URLs to redirect user in another page. Escapes HTML for parameter values in order to stop XSS attacks based on [unsecured links](https://www.owasp.org/index.php/XSS_(Cross_Site_Scriptin…

UrlSearchParams

Manipulate URL GET parameters and hash.

Similar to URLSearchParams.

In addition:

  • Compatible with >IE5

  • Can read and manipulate hash parameters in the same manner as in url through .hash property.

var params = new UrlSearchParams('http://example.com?varA=foo&varB=bar#varC=foobar');
params.get('varA'); //foo
params.hash.get('varC'); //foobar
params.hash.set('varD', 'braf');
params.toString(); //varA=foo&varB=bar#varC=foobar&varD=braf
  • toString method sorts URL parameters by variable name.That's helpfull to get always the same URL for the same set of parameters since the order of them will always be the same. Helps to keep your SEO score without penalty due to duplicated content on URLs with different parameters' order.
var params = new UrlSearchParams('http://example.com?varB=bar&varA=foo');
params.toString(); //varA=foo&varB=bar
  • Escapes HTML for parameter values in order to stop XSS attacks based on unsecured links
var badBadURL = "http://map.openseamap.org/map/?zoom=15&mlat=53.62053&mlon=11.46929&mtext=%3Cscript%3E%0A%20alert(%27Hello%20World!%27)%3B%0A%3C%2Fscript%3E&layers=BTFFFFFFFFF0FFFFFFFF";
var params = new UrlSearchParams(badBadURL);
params.toString(); //layers=BTFFFFFFFFF0FFFFFFFF&mlat=53.62053&mlon=11.46929&mtext=%26lt%3Bscript%26gt%3B%0A%20alert(%26%2339%3BHello%20World!%26%2339%3B)%3B%0A%26lt%3B%2Fscript%26gt%3B&zoom=15

Note

The following methods are missing from the original spec:

  • append - Append multiple parameters with the same name. This implementation doesn't support multiple values under same parameter name.
  • getAll - Get all values for a specific parameter. Would be needed if append was implemented.
/**
* Similar to URLSearchParams. [https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams]
*
* [https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#Output_Encoding_Rules_Summary]
* Escapes HTML for parameter values in order to stop XSS attacks based on unsecured links and is compatible with >IE5
*
* Copyright 2017 dimitrk
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
function UrlSearchParams(url) {
url = url || window.location.href;
var paramPairs, paramComponents, urlParamMap;
this["delete"] = this.remove = function (key) {
delete urlParamMap[key];
};
this.entries = function () {
var entries = [];
for (var key in urlParamMap) {
if (this.has(key)) {
entries.push([key, urlParamMap[key]]);
}
}
entries = entries.sort(function(entryA, entryB) {
if (entryA[0].toLowerCase() > entryB[0].toLowerCase()) {
return 1;
}
if (entryA[0].toLowerCase() < entryB[0].toLowerCase()) {
return -1;
}
return 0;
});
return entries;
};
this.get = function (key) {
return urlParamMap[key];
};
this.has = function (key) {
return urlParamMap.hasOwnProperty(key);
};
this.keys = function () {
var keys = [];
for (var key in urlParamMap) {
if (this.has(key)) {
keys.push(key);
}
}
return keys;
};
this.set = function (key, val) {
urlParamMap[key] = val;
};
this.toString = function () {
var paramsString = '';
var entries = this.entries();
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
if (this.has(entry[0])) {
paramsString += '&' + entry[0] + '=' + encodeURIComponent(this._unesc(entry[1]));
}
}
if (this.hash && this.hash.entries().length) {
paramsString += '#' + this.hash.toString();
}
return paramsString.substr(1);
};
this.values = function () {
var values = [];
for (var key in urlParamMap) {
if (this.has(key)) {
values.push(urlParamMap[key]);
}
}
return values;
};
this._esc = function (s) {
return String(s)
.replace(/</g, '&lt;')
.replace(/'/g, '&#39;')
.replace(/"/g, '&quot;')
.replace(/>/g, '&gt;')
.replace(/&/g, '&amp;');
};
this._unesc = function (s) {
return String(s)
.replace(/&lt;/g, '<')
.replace(/&#39;/g, '\'')
.replace(/&quot;/g, '"')
.replace(/&gt;/g, '>')
.replace(/&amp;/g, '&');
};
urlParamMap = {};
paramPairs = url.substr(url.indexOf('?') + 1);
var urlHash;
if (paramPairs.indexOf('#') > -1) {
urlHash = paramPairs.substr(paramPairs.indexOf('#') + 1, paramPairs.length);
paramPairs = paramPairs.substr(0, paramPairs.indexOf('#'))
}
paramPairs = paramPairs.split('&');
if (urlHash) {
this.hash = new UrlSearchParams(urlHash);
} else {
this.hash = undefined;
}
for (var i = 0; i < paramPairs.length; i++) {
paramComponents = paramPairs[i].split('=');
if (paramComponents.length === 2) {
urlParamMap[paramComponents[0]] = this._esc(decodeURIComponent(paramComponents[1]));
}
}
}
var url = "http://map.openseamap.org/map/?zoom=15&mlat=53.62053&mlon=11.46929&mtext=%3Cscript%3E%0A%20alert(%27Hello%20World!%27)%3B%0A%3C%2Fscript%3E&layers=BTFFFFFFFFF0FFFFFFFF";
aUrl = new UrlSearchParams(url);
//Set
aUrl.set('text', 'sometext');
//Get
aUrl.get('text');
//Has
aUrl.has('text'); // True
//Delete-Remove
aUrl.delete('text');
aUrl.has('text'); // False
//Iterating
for (var key of aUrl.keys()) {
console.log(key);
}
for (var val of aUrl.values()) {
console.log(val);
}
for (var pair of aUrl.entries()) {
console.log(pair[0] + ', ' + pair[1]);
}
console.log(aUrl.toString())
@DimitrK
Copy link
Author

DimitrK commented Dec 12, 2017

Similar to URLSearchParams. Manipulate URL GET parameters. Escapes HTML for parameter values in order to stop XSS attacks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment