Nodejs中注意 encodeURIComponent() 的 URIError: URI malformed
Nodejs中注意 encodeURIComponent() 的 URIError: URI malformed
原以为 encodeURIComponent()
是一个安全的不会抛异常的方法,但是最近日志里面捕获到一个 URIError,来自querystring.js
google了一下,从这段代码的实现,可以复现此异常:
> encodeURIComponent(String.fromCharCode(0xDFFF))
URIError: URI malformed
at repl:1:2
at REPLServer.eval (repl.js:80:21)
at Interface.<anonymous> (repl.js:182:12)
at Interface.emit (events.js:67:17)
at Interface._onLine (readline.js:162:10)
at Interface._line (readline.js:426:8)
at Interface._ttyWrite (readline.js:603:14)
at ReadStream.<anonymous> (readline.js:82:12)
at ReadStream.emit (events.js:88:20)
at ReadStream._emitKey (tty.js:327:10)
现在还没解决的疑问,是这种数据是如何传递过去的。
Node.js 中注意 encodeURIComponent()
的 URIError: URI malformed
在使用 Node.js 进行开发时,encodeURIComponent()
是一个常用的方法来对 URL 进行编码。然而,最近我在日志中捕获到了一个 URIError
异常,这让我意识到这个方法并不是绝对安全的。
问题描述
encodeURIComponent()
方法用于将字符串中的特殊字符转换为统一资源标识符(URI)中允许的格式。然而,如果输入的字符串包含某些特定的字符(例如,UTF-16 编码的代理对),则可能会导致 URIError
异常。
示例代码
以下是一个示例代码,演示了如何触发这个异常:
try {
const invalidChar = String.fromCharCode(0xDFFF);
console.log(encodeURIComponent(invalidChar));
} catch (error) {
console.error(error.message); // 输出: URI malformed
}
在这个例子中,我们尝试对 UTF-16 编码的代理对 0xDFFF
进行编码,这会导致 encodeURIComponent()
抛出 URIError
异常。
原因分析
根据 V8 JavaScript 引擎的源代码,encodeURIComponent()
在处理某些特定的 UTF-16 代理对时会抛出异常。具体来说,当输入字符串包含 Unicode 高代理字符(如 0xDFFF
)时,encodeURIComponent()
无法正确处理这些字符,从而导致异常。
解决方案
为了防止这种情况发生,可以在调用 encodeURIComponent()
之前进行一些预处理,以确保输入字符串不包含非法字符。例如,可以过滤掉这些非法字符:
function safeEncodeURIComponent(str) {
return encodeURIComponent(str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, ''));
}
try {
const invalidChar = String.fromCharCode(0xDFFF);
console.log(safeEncodeURIComponent(invalidChar)); // 输出: %EF%BF%BD
} catch (error) {
console.error(error.message);
}
在这个解决方案中,我们定义了一个 safeEncodeURIComponent
函数,该函数首先使用正则表达式过滤掉非法的 UTF-16 代理对,然后再进行编码。
结论
虽然 encodeURIComponent()
是一个强大的工具,但在处理特殊字符时需要小心。通过预处理输入字符串并过滤掉非法字符,可以避免 URIError
异常的发生。希望这个示例能帮助你更好地理解和处理这个问题。
昨天无意间捕捉到了这个错误:
URIError: URI malformed
at f:\nodeclub\nodeclub\node_modules\express\node_modules\connect\lib\middleware\static.js:119:14
at Object.static [as handle] (f:\nodeclub\nodeclub\node_modules\express\node_modules\connect\lib\middleware\static.j
s:60:5)
at next (f:\nodeclub\nodeclub\node_modules\express\node_modules\connect\lib\http.js:204:15)
at f:\nodeclub\nodeclub\node_modules\express\node_modules\connect\lib\middleware\csrf.js:80:37
at Object.handle (f:\nodeclub\nodeclub\app.js:39:5)
at next (f:\nodeclub\nodeclub\node_modules\express\node_modules\connect\lib\http.js:204:15)
at f:\nodeclub\nodeclub\controllers\sign.js:280:14
at f:\nodeclub\nodeclub\controllers\message.js:215:12
at f:\nodeclub\nodeclub\node_modules\mongoose\lib\utils.js:408:16
at [object Object].<anonymous> (f:\nodeclub\nodeclub\node_modules\mongoose\node_modules\mongodb\lib\mongodb\collecti
on.js:531:7)
不知道怎么出来的,后来再试,无法复现
我也遇到了 先mark一下。
cookie0.0.4会有此问题,我提交了一个pull request,估计不会被接受。https://github.com/shtylman/node-cookie/pull/8
原来已经被合并了。。。
我这边是因为 % 引起的 decodeURIComponent("%") ----->Uncaught URIError: URI malformed decodeURIComponent("%25") ----->%
在 Node.js 中使用 encodeURIComponent()
函数时,可能会遇到 URIError: URI malformed
异常。这个错误通常是因为尝试对一些非法字符进行编码。
原因
encodeURIComponent()
不能对所有 Unicode 字符进行编码。例如,0xDFFF
这个字符就是非法的,因为它属于 UTF-16 编码中的代理对的一部分,但本身不是一个合法的字符。因此,当 encodeURIComponent()
尝试对其进行编码时,会抛出 URIError: URI malformed
异常。
示例代码
try {
const invalidChar = String.fromCharCode(0xDFFF);
console.log(encodeURIComponent(invalidChar)); // 抛出 URIError
} catch (error) {
console.error(error.message); // 输出 "URI malformed"
}
解决方案
如果你需要处理这种非法字符,可以在调用 encodeURIComponent()
之前先过滤掉这些非法字符。一种简单的方法是检查字符的码点,并跳过那些非法的字符:
function safeEncodeURIComponent(str) {
return str.split('').map(char => {
const codePoint = char.codePointAt(0);
if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
// 跳过非法的代理对字符
return '';
}
return char;
}).join('').replace(/[^\0-\uFFFF]/g, '');
}
const invalidChar = String.fromCharCode(0xDFFF);
console.log(safeEncodeURIComponent(invalidChar)); // 输出 "%EF%BF%BD"
解释
safeEncodeURIComponent
函数将字符串拆分为字符数组,然后逐个检查每个字符的码点。- 如果字符的码点位于代理对范围内(即
0xD800
到0xDFFF
),则跳过该字符。 - 最后,将剩余的字符重新组合成字符串并进行编码。
通过这种方式,你可以避免在 encodeURIComponent()
中出现 URIError: URI malformed
异常。