Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

URLSearchParams fails to get first parameter when '#' is in url

Tags:

javascript

This seems like a bug in this API, though I don't know where to report it. So I am posting here for help. Mozilla docs here URLSearchParams

If window.location.href contains a # then URLSearchParams.get fails to retrieve the first search parameter

const location = 'http://localhost:3000/path?referrer=https://google.com';
const myURL = new URL(location).searchParams.get('referrer')
// myURL === 'https://google.com

// in one line:
(new URL('http://localhost:3000/path?referrer=https://google.com')).searchParams.get('referrer')

But this same example slightly tweaking the window location will fail

const location = 'http://localhost:3000/#/path?referrer=https://google.com';
const myURL = new URL(location).searchParams.get('referrer')
// myURL === null

// in one line
(new URL('http://localhost:3000/#/path?referrer=https://google.com')).searchParams.get('referrer')

This example is using new URL(location).searchParams.get but will yield the exact same functionality if you tweak it to using new URLSearchParams(...).get

like image 762
Jeremy Avatar asked Feb 28 '18 23:02

Jeremy


2 Answers

In URL standards, # introduces a fragment component that has no special meaning to the transport protocol and is treated as secondary or "user specified" information whose semantics are treated as unknown. The # and everything following it in the URL is passed to the client application (e.g. HTML browser) without interpretation. You can access the fragment value in JavaScript using window.location.hash.

Any URL parameters must precede a fragment identifier or they will be included in fragment content and not parsed as parameters.

A # could be included in the URL path or parameters, but would need to be percentage escaped as %23. I would strongly advise against writing a router or creating a server side folder for static content that contains # in the path, even if technically possible.

Allowing users to enter # in form inputs would normally be handled automatically by encoding the input value with encodeURIComponent() before submitting the form.

Data URLs that have been formulated using clear text of a particular MIME type need to percentage escape any and every # within the text to avoid truncating data represented by the URL.

like image 175
traktor Avatar answered Oct 21 '22 07:10

traktor


I know this issue is a bit old, but I ran into the same issue recently and created a simple function to fix the Url hash & search params:

   function fixUrlHash(url) {
  let fixedUrl = new URL(url);
  let search = url.search;
  let hash = url.hash;
  const position = url.hash.indexOf('?');
  if(search.length <= 1 && position >= 0) {
    search = hash.substr(position);
    hash = hash.substr(0, position);
    fixedUrl.hash = hash;
    fixedUrl.search = search;
    fixedUrl.href = fixedUrl.toString();
  }
  return fixedUrl;
}

This simply returns a new URL object with the fixed hash & search params. After you get the fixed URL value, you can load the new URL in the browser if original URL is the browser location.

like image 44
Silkster Avatar answered Oct 21 '22 06:10

Silkster