使 Node REST Client 期望 UTF-8 JSON 内容以避免 BOM 解析错误
Make Node REST Client expect UTF-8 JSON content to avoid BOM parsing error
我有一个 Node.js 应用程序使用 Node REST 客户端向服务器发出 HTTP GET 请求,目标是 JSON 格式的文件。当此文件以不带 BOM 的 UTF-8 编码时一切顺利。
但是,当目标文件编码为带 BOM 的 UTF-8 时,应用程序会在 client.get 调用期间崩溃。即使当我将该调用包装在 try / catch 中以试图防止崩溃并得到错误时,我也会得到这个堆栈跟踪:
events.js:188
throw err;
^
Error: Unhandled "error" event. (Error parsing response. response: [{}], error: [SyntaxError: Unexpected token in JSON at position 0])
at exports.Client.emit (events.js:186:19)
at C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:457:57
at Object.parse (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\nrc-parser-manager.js:140:17)
at ConnectManager.handleResponse (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:538:32)
at ConnectManager.handleEnd (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:531:18)
at IncomingMessage.<anonymous> (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:678:34)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:139:11)
此处代码块未显示 IntelliJ 所做的是 U+FEFF zero width no-break space Unicode code point, marked by < X > in the following stack trace line: Error: Unhandled "error" event. (Error parsing response. response: [< X >{}], error: [SyntaxError: Unexpected token < X > in JSON at position 0])
. So what sems to happens is that the Client is trying to read the file content as a Unicode encoded String,而不是没有 BOM 的 UTF-8 JSON。所以它认为BOM是U+FEFF Unicode字符。
我搜索了 SO 并发现了很多关于 setting mimetypes for the Client but I still get the error. I have also read the node-rest-client docs and it seems that setting a response parser 的问题,但是滚动到 JSON parser 表明它是与设置 mimetypes 相同。
所以我得到了这个:
const options ={
mimetypes:{
json:["application/json","application/json; charset=utf-8","application/json;charset=utf-8"]
}
};
const client = new Client(options);
尝试将字符集设置为 UTF-8 但错误相同。
有人知道我做错了什么吗?或者这是 Node REST 客户端的问题?
感谢您的帮助。
-- 编辑
这是我的 GET 请求函数代码:
let Client = require('node-rest-client').Client;
const options ={
mimetypes:{
json:["application/json","application/json; charset=utf-8","application/json;charset=utf-8"]
}
};
const client = new Client(options);
// Reads file contents and calls callback function with data
exports.readFromUrl = (req, fileUrl, callback) => {
client.get(fileUrl, (data, resp) => {
if (resp.statusCode === 200) {
callback(data);
} else {
callback("");
}
}).on('error', (err) => {
callback("");
});
};
最终解决方案:
以防万一有人因为类似问题在这里绊倒,我最终用自定义解析器替换了 Node REST 客户端 JSON 解析器,该解析器过滤掉无效字符以将有效 JSON 传递给回调。
我是这样做的(使用之前提到的文档)。
const Client = require('node-rest-client').Client;
const client = new Client();
// Remove existing regular parsers (otherwise JSON parser still gets called first)
client.parsers.clean();
client.parsers.add({
"name": "cleanInput",
"isDefault": false,
"match": function (response) {
// Match evey response to replace default parser
return true;
},
"parse": function (byteBuffer, nrcEventEmitter, parsedCallback) {
let parsedData = null;
try {
const cleanData = cleanString(byteBuffer.toString());
parsedData = JSON.parse(cleanData);
parsedData.parsed = true;
// Emit custom event
nrcEventEmitter('parsed', 'Data has been parsed ' + parsedData);
// Pass parsed data to client request method callback
parsedCallback(parsedData);
} catch(err) {
nrcEventEmitter('error', err);
}
}
});
// Only keeps unicode characters with codes lesser than 127 to avoid forbidden characters in JSON
function cleanString(input) {
let output = "";
for (let i=0; i < input.length; i++) {
if (input.charCodeAt(i) < 127) {
output += input.charAt(i);
}
}
return output;
}
JSON 解析器被指定为 NOT 接受 Byte-Order 标记。
因此,您的服务器因 'malformed' 客户端 GET 请求而崩溃。
该问题应在您的服务器处理 GET 请求时解决,而不是通过更改 JSON 解析器规范来解决。
我建议在服务器解析之前过滤所有 GET 请求中的字节顺序标记。
in express how multiple callback works in app.get
这向您展示了单个中间件如何在传递到该 GET 路径的实际回调之前执行 pre-filtering 个 GET 主体。
我有一个 Node.js 应用程序使用 Node REST 客户端向服务器发出 HTTP GET 请求,目标是 JSON 格式的文件。当此文件以不带 BOM 的 UTF-8 编码时一切顺利。
但是,当目标文件编码为带 BOM 的 UTF-8 时,应用程序会在 client.get 调用期间崩溃。即使当我将该调用包装在 try / catch 中以试图防止崩溃并得到错误时,我也会得到这个堆栈跟踪:
events.js:188
throw err;
^
Error: Unhandled "error" event. (Error parsing response. response: [{}], error: [SyntaxError: Unexpected token in JSON at position 0])
at exports.Client.emit (events.js:186:19)
at C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:457:57
at Object.parse (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\nrc-parser-manager.js:140:17)
at ConnectManager.handleResponse (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:538:32)
at ConnectManager.handleEnd (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:531:18)
at IncomingMessage.<anonymous> (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:678:34)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:139:11)
此处代码块未显示 IntelliJ 所做的是 U+FEFF zero width no-break space Unicode code point, marked by < X > in the following stack trace line: Error: Unhandled "error" event. (Error parsing response. response: [< X >{}], error: [SyntaxError: Unexpected token < X > in JSON at position 0])
. So what sems to happens is that the Client is trying to read the file content as a Unicode encoded String,而不是没有 BOM 的 UTF-8 JSON。所以它认为BOM是U+FEFF Unicode字符。
我搜索了 SO 并发现了很多关于 setting mimetypes for the Client but I still get the error. I have also read the node-rest-client docs and it seems that setting a response parser 的问题,但是滚动到 JSON parser 表明它是与设置 mimetypes 相同。
所以我得到了这个:
const options ={
mimetypes:{
json:["application/json","application/json; charset=utf-8","application/json;charset=utf-8"]
}
};
const client = new Client(options);
尝试将字符集设置为 UTF-8 但错误相同。
有人知道我做错了什么吗?或者这是 Node REST 客户端的问题?
感谢您的帮助。
-- 编辑 这是我的 GET 请求函数代码:
let Client = require('node-rest-client').Client;
const options ={
mimetypes:{
json:["application/json","application/json; charset=utf-8","application/json;charset=utf-8"]
}
};
const client = new Client(options);
// Reads file contents and calls callback function with data
exports.readFromUrl = (req, fileUrl, callback) => {
client.get(fileUrl, (data, resp) => {
if (resp.statusCode === 200) {
callback(data);
} else {
callback("");
}
}).on('error', (err) => {
callback("");
});
};
最终解决方案:
以防万一有人因为类似问题在这里绊倒,我最终用自定义解析器替换了 Node REST 客户端 JSON 解析器,该解析器过滤掉无效字符以将有效 JSON 传递给回调。
我是这样做的(使用之前提到的文档)。
const Client = require('node-rest-client').Client;
const client = new Client();
// Remove existing regular parsers (otherwise JSON parser still gets called first)
client.parsers.clean();
client.parsers.add({
"name": "cleanInput",
"isDefault": false,
"match": function (response) {
// Match evey response to replace default parser
return true;
},
"parse": function (byteBuffer, nrcEventEmitter, parsedCallback) {
let parsedData = null;
try {
const cleanData = cleanString(byteBuffer.toString());
parsedData = JSON.parse(cleanData);
parsedData.parsed = true;
// Emit custom event
nrcEventEmitter('parsed', 'Data has been parsed ' + parsedData);
// Pass parsed data to client request method callback
parsedCallback(parsedData);
} catch(err) {
nrcEventEmitter('error', err);
}
}
});
// Only keeps unicode characters with codes lesser than 127 to avoid forbidden characters in JSON
function cleanString(input) {
let output = "";
for (let i=0; i < input.length; i++) {
if (input.charCodeAt(i) < 127) {
output += input.charAt(i);
}
}
return output;
}
JSON 解析器被指定为 NOT 接受 Byte-Order 标记。
因此,您的服务器因 'malformed' 客户端 GET 请求而崩溃。
该问题应在您的服务器处理 GET 请求时解决,而不是通过更改 JSON 解析器规范来解决。
我建议在服务器解析之前过滤所有 GET 请求中的字节顺序标记。
in express how multiple callback works in app.get
这向您展示了单个中间件如何在传递到该 GET 路径的实际回调之前执行 pre-filtering 个 GET 主体。