1

URLSearchParams.set(key, value) URIEncodes the values its given, producing ugly non-specified urls.

The following test is based off this list of url friendly characters

const url = new URL("http://www.example.com/path");
const test = "abc123+-_$#%?@,"
url.searchParams.set("foo", test);

console.log(`What foo should be: ${test}`);
console.log(`What foo is: ${url.search}`)

Is there a way to use URLSearchParams from URL.searchParams to update a search param to the value given and not an encoding of it?

Seph Reed
  • 8,797
  • 11
  • 60
  • 125
  • Why would you want to do that? If `test` was something like `bar&baz=bla` doing it the way you want would create both a `bar` and a `baz` param. Also note that `#` has to be converted no matter what, or it will be considered as the URL's hash, and if you need to decode this character, the others would also need to be encoded or you won't be able to tell apart the original sequence `%23` from the original `#` that got encoded to `%23`. – Kaiido Mar 02 '22 at 03:06
  • 1
    The reason a UX developer would want to have readable URLs is so users can read them. And while you are correct that the `&` symbol should be avoided, `#` `?` and `=` can be used without issue. Give it a try! – Seph Reed Mar 02 '22 at 22:26
  • And why a UX developper would use an URLSearchParam to display something to their users? If you want to show them the content of the POST params show just that, the URL is for the server to read. And `#` is the one that's not ok, look at your answer's result. – Kaiido Mar 02 '22 at 23:02
  • 1
    Using URLS as a primary user interface is indeed silly, but treating them as non-user facing is also not a great experience. I've tested use of `#` and had no issues. It only registers as a hash if it's at the end. Try it out. – Seph Reed Mar 03 '22 at 00:10
  • No `#` is the hash marker anywhere. Your own examples in your own answer to your own question demonstrate that: the output of the first snippet is `What foo is: ?foo=abc123+-_$%23%?@,`, the `#` character has been converted to `%23`. Because the `.search` setter srill does encode this char, because it would be defining the hash otherwise. If you want to show something "friendly" to your users don't show the URL, show each components on their own, decoded. – Kaiido Mar 03 '22 at 00:27

1 Answers1

6

If one wants all their searchParams to be unencoded, they can just set url.search to an unencoded version of itself:

const url = new URL("http://www.example.com/path");
const test = "abc123+-_$#%?@,"
url.searchParams.set("foo", test)
url.search = decodeURIComponent(url.search)

console.log(`What foo should be: ${test}`);
console.log(`What foo is: ${url.search}`)

If one only wants the specified key to be unencoded, it takes some extra

const testUrl = new URL("http://www.example.com/path");
testUrl.searchParams.set("bar", "++ ++");

const testVal = "abc123+-_$#%?@,";
setValueUnencoded(testUrl, "foo", testVal);


console.log(`What foo should be: ${testVal}`);
console.log(`What foo is: ${testUrl.search}`)


function setValueUnencoded(url, key, value) {
  url.searchParams.set(key, value);
  const entries = Array.from(url.searchParams.entries());
  url.search = "";
  entries.forEach(item => {
    if (item[0] === key) { return; }
    url.searchParams.set(item[0], item[1]);
  });
  url.search += `${key}=${value}`;
}
Seph Reed
  • 8,797
  • 11
  • 60
  • 125