Why does decodeURIComponent('%') lock up my browser?
I was just testing something with AJAX and I found that on success if I alert
开发者_JAVA技巧alert(decodeURI('%'));
or
alert(encodeURIComponent('%'));
the browser errors out with the following code.
$.ajax({
type: "POST",
url: "some.php",
data: "",
success: function(html){
alert(decodeURIComponent('%'));
// alert(decodeURI('%'));
}
});
If I use any other string it works just fine.
Is it something that I missed?Recently a decodeURIComponent
in my code tripped over the ampersand %
and googling led me to this question.
Here's the function I use to handle %
which is shorter than the version of Ilia:
function decodeURIComponentSafe(s) {
if (!s) {
return s;
}
return decodeURIComponent(s.replace(/%(?![0-9][0-9a-fA-F]+)/g, '%25'));
}
It
- returns the input value unchanged if input is empty
- replaces every
%
NOT followed by a two-digit (hex) number with%25
- returns the decoded string
It also works with the other samples around here:
decodeURIComponentSafe("%%20Visitors") // % Visitors
decodeURIComponentSafe("%Directory%20Name%") // %Directory Name%
decodeURIComponentSafe("%") // %
decodeURIComponentSafe("%1") // %1
decodeURIComponentSafe("%3F") // ?
Chrome barfs when trying from the console. It gives an URIError: URI malformed. The % is an escape character, it can't be on its own.
The point is that if you use single %
it breaks the logic of decodeURIComponent()
function as it expects two-digit data-value followed right after it, for example %20
(space).
There is a hack around. We need to check first if the decodeURIComponent()
actually can run on given string and if not return the string as it is.
Example:
function decodeURIComponentSafe(uri, mod) {
var out = new String(),
arr,
i = 0,
l,
x;
typeof mod === "undefined" ? mod = 0 : 0;
arr = uri.split(/(%(?:d0|d1)%.{2})/);
for (l = arr.length; i < l; i++) {
try {
x = decodeURIComponent(arr[i]);
} catch (e) {
x = mod ? arr[i].replace(/%(?!\d+)/g, '%25') : arr[i];
}
out += x;
}
return out;
}
Running:
decodeURIComponent("%Directory%20Name%")
will result in Uncaught URIError: URI malformed
error
while:
decodeURIComponentSafe("%Directory%20Name%") // %Directory%20Name%
will return the initial string.
In case you would want to have a fixed/proper URI and have %
turned into %25
you would have to pass 1
as additional parameter to the custom function:
decodeURIComponentSafe("%Directory%20Name%", 1) // "%25Directory%20Name%25"
The problem here is you're trying to decode the %
. This is not a valid encoded string. I think you want to encode the %
instead.
decodeURI('%') // URIError
encodeURI('%') // '%25'
Unfortunately some of the answers here failed to satisfy my code, so I made an alternative solution. If someone comes looking by with the same problem.
You can use a try...catch block to decode safely. If the string is decodable it will decode, if not, it returns the same string as it is already decoded.
function decodeURIComponentSafely(uri) {
try {
return decodeURIComponent(uri)
} catch(e) {
console.log('URI Component not decodable: ' + uri)
return uri
}
}
Both decodeURI('%')
and decodeURIcomponent('%')
cannot work because the URL is malformed (a single % is not valid as a url or url component)
Uncaught URIError: URI malformed
encodeURIComponent()
works
I had the same issue as OP and found this useful topic. Had to find a way to check if URI string contained percent sign before using decodeURIComponent().
The piece of code from Ilia Rostovtsev works great except for URI which contains encoded characters like %C3 (where percent sign is starting by [A-F]) because the regex used doesn't handle them (only % followed by a decimal).
I replaced the following line:
x = mod ? arr[i].replace(/%(?!\d+)/g, '%25') : arr[i];
by
x = mod ? arr[i].replace(/%(?!\d|[ABCDEF]+)/g, '%25') : arr[i];
Now, it is working as the regex will reject %1A to %9F and also %A1 to %F9
The endless-loop or lock up may be due to a bug in jquery.
You can set a breakpoint in jquery at a point which is likely causing the 'lock-up'.
Decode doesn't make sense with just %
provided, as percent-encoding
is followed by alphanumericals referring to a given character in the ASCII table, and should normally yield an URIError in Opera, Chrome, FF.
Use the browser built in function encodeURI
if you are looking for the 'url-encoded' notation of the percent-character:
encodeURI('%')
//>"%25"
精彩评论