为什么解码 URI 解码的字符比它应该解码的要多?



我刚刚阅读了有关decodeURI(MDN,ES6规范)的内容,有些东西引起了我的注意:

不会替换 encodeURI 无法引入的转义序列。

因此,它应该只解码encodeURI编码的字符。

// None of these should be escaped by `encodeURI`.
const unescaped = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'();/?:@&=+$,#";
const data = [...unescaped].map(char => ({
"char": char,
"encodeURI(char)": encodeURI(char),
"encodePercent(char)": encodePercent(char),
"decodeURI(encodePercent(char))": decodeURI(encodePercent(char))
}));
console.table( data );
console.log( "Check the browser's console." );
function encodePercent(string) {
return string.replace(/./g, char => "%" + char.charCodeAt(0).toString(16));
}

为什么这只适用于; / ? : @ & = + $ , #

规范规定了以下步骤:

  1. unescapedURISet是一个字符串,其中包含在 uriReserved 和uriUnericed中有效的每个代码单元的一个实例加上 "#">

让我们来看看uriReserved,瞧:

uri保留 ::: 其中之一

; / ? : @ & = + $ ,

然后是以下步骤:

  1. Return Encode(uriString, unescapedURISet).

对字符串进行编码的所有内容进行编码,但未转义 URISet中的字符除外,其中包括; / ? : @ & = + $ ,.

这意味着encodeURI永远无法为uriReserved 和 uriUnescape中的任何内容引入转义序列。

有趣的是,decodeURI是这样定义的:

  1. 让 reservedURISet 是一个字符串,其中包含在uriReserved中有效的每个代码单元的一个实例加上"#"。

  2. return Decode(uriString, reservedURISet).

解码的工作方式与编码类似,并解码除保留的 URISet中的字符之外的所有内容。显然,只有uriReserve的字符被排除在解码之外。而那些恰好是; / ? : @ & = + $ ,

问题仍然是为什么标准指定了这一点。如果他们在保留的URISet中包含uriUnescaped,那么行为将完全符合介绍中所述。可能是个错误?

最新更新