URL encode sees “&” (ampersand) as “&” HTML entity
JavascriptUrlencodeJavascript Problem Overview
I am encoding a string that will be passed in a URL (via GET). But if I use escape
, encodeURI
or encodeURIComponent
, &
will be replaced with %26amp%3B
, but I want it to be replaced with %26
. What am I doing wrong?
Javascript Solutions
Solution 1 - Javascript
Without seeing your code, it's hard to answer other than a stab in the dark. I would guess that the string you're passing to encodeURIComponent(), which is the correct method to use, is coming from the result of accessing the innerHTML property. The solution is to get the innerText/textContent property value instead:
var str,
el = document.getElementById("myUrl");
if ("textContent" in el)
str = encodeURIComponent(el.textContent);
else
str = encodeURIComponent(el.innerText);
If that isn't the case, you can use the replace() method to replace the HTML entity:
encodeURIComponent(str.replace(/&/g, "&"));
Solution 2 - Javascript
If you did literally this:
encodeURIComponent('&')
Then the result is %26
, you can test it here. Make sure the string you are encoding is just &
and not &
to begin with...otherwise it is encoding correctly, which is likely the case. If you need a different result for some reason, you can do a .replace(/&/g,'&')
before the encoding.
Solution 3 - Javascript
There is HTML and URI encodings. &
is &
encoded in HTML while %26
is &
in URI encoding.
So before URI encoding your string you might want to HTML decode and then URI encode it :)
var div = document.createElement('div');
div.innerHTML = '&AndOtherHTMLEncodedStuff';
var htmlDecoded = div.firstChild.nodeValue;
var urlEncoded = encodeURIComponent(htmlDecoded);
result %26AndOtherHTMLEncodedStuff
Hope this saves you some time
Solution 4 - Javascript
Just to be clear, you should never be using encodeURI()
and encodeURIComponent()
. If you disagree, just look at its results...
console.log(encodeURIComponent('@#$%^&*'));
>Input: ^&*
.
>
>Output: %40%23%24%25%5E%26*
.
That's not right, is it? *
did not get converted! I hope you're not using this as a server-side cleansing function, because *
will not be treated as input but as commands, i.e., imagine deleting a user's alleged file with rm *
. Well, I hope you're not using encodeURI() or encodeURIComponent()!
TLDR: You actually want fixedEncodeURIComponent()
and fixedEncodeURI()
.
MDN encodeURI() Documentation...
> >function fixedEncodeURI(str) { > return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']'); >} >
MDN encodeURIComponent() Documentation...
> >function fixedEncodeURIComponent(str) { > return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { > return '%' + c.charCodeAt(0).toString(16); > }); >} >
With these functions, use fixedEncodeURI()
to encode a single URL piece, whereas fixedEncodeURIComponent()
will encode URL pieces and connectors; or, more simply, fixedEncodeURI()
will not encode +@?=:#;,$&
(as &
and +
are common URL operators), but fixedEncodeURIComponent()
will.