Nodejs http.request 报错 Parse error
Nodejs http.request 报错 Parse error
用nodejs 做客户端向别的服务器发送请求的时候 如果别的服务器的响应码是自定义的 而不是默认的,
比如说会出现20000的响应码 这种报错怎末解决
exports.get = function(req, res){
var data = ‘<Request>’+
’ <Id>’+‘11’+’</Id>’+
’</Request>’
var opt = {
method: “POST”,
host: interfaceConfig.emallServer,
port: interfaceConfig.emallPort,
path: interfaceConfig.emallUser,
headers: {
“Content-Type”: ‘text/xml’,
“Content-Length”: data.length
}
};
var request = http.request(opt, function (serverFeedback) {
serverFeedback.setEncoding(‘utf8’);
serverFeedback.on(‘data’, function (data) {
console.log(data);
});
});
request.write(data + “\n”);
request.end();
};
报错:
Error :Parse Error
at Socket.socketOnData (http.js :1583:20)
at Tcp.onread(net.js:527:27)
自己抓包看了 响应码是20004但没有响应描述 报错如上 这种问题怎么解决啊
POST /emall/interface/getUserInfoByToken HTTP/1.1
Content-Type: text/xml
Content-Length: 48
Host: 211.140.7.142
Connection: keep-alive
<Request> <Id>11</Id></Request> HTTP/1.1 20004
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=C8DEB8E76971731937CCF9CCA9D01B39; Path=/emall/; HttpOnly
Content-Length: 0
Date: Thu, 15 May 2014 03:10:30 GMT
对于这个问题,http.request
在处理非标准HTTP状态码(例如 20004
)时可能会遇到解析错误。这是因为 Node.js 默认的HTTP模块只支持标准的状态码。为了解决这个问题,你可以手动处理这些非标准状态码。
以下是一个示例代码,展示了如何处理这种场景:
const http = require('http');
exports.get = function(req, res) {
var data = '<Request>' +
'<Id>11</Id>' +
'</Request>';
var opt = {
method: "POST",
host: '211.140.7.142',
port: 80,
path: '/emall/interface/getUserInfoByToken',
headers: {
"Content-Type": 'text/xml',
"Content-Length": Buffer.byteLength(data)
}
};
var request = http.request(opt, function(serverFeedback) {
let responseData = '';
serverFeedback.setEncoding('utf8');
serverFeedback.on('data', function(chunk) {
responseData += chunk;
});
serverFeedback.on('end', function() {
console.log('Response Data:', responseData);
// 检查自定义状态码并进行相应处理
if (serverFeedback.statusCode === 20004) {
console.log('Custom status code received:', serverFeedback.statusCode);
// 在这里添加你的错误处理逻辑
} else if (serverFeedback.statusCode >= 200 && serverFeedback.statusCode < 300) {
// 处理成功的情况
console.log('Success response received:', serverFeedback.statusCode);
res.send(responseData);
} else {
console.error('Unexpected status code:', serverFeedback.statusCode);
res.status(serverFeedback.statusCode).send(responseData);
}
});
});
request.on('error', function(e) {
console.error(`Problem with request: ${e.message}`);
});
request.write(data);
request.end();
};
解释
- 数据编码:使用
Buffer.byteLength(data)
来计算Content-Length
,而不是data.length
。 - 响应处理:通过监听
data
事件收集所有响应数据,并在end
事件中处理最终结果。 - 自定义状态码处理:在
end
事件中检查statusCode
是否为20004
,并根据需要进行处理。 - 错误处理:添加了对请求错误的处理。
这样可以确保你能够正确地处理非标准HTTP状态码,并且不会因为解析错误而中断程序执行。
比较奇怪的设计. 好像nodejs的http没戏(不确定), 底层http parser报的错:
// deps/http_parser/http_parser.c
if (parser->status_code > 999) { // 如果自定义的状态码,超过了999, 直接报错 ==> 没有超过的话, 仍然是可接受的
SET_ERRNO(HPE_INVALID_STATUS);
goto error;
}
// lib/http.js
var ret = parser.execute(d, start, end - start);
if (ret instanceof Error) {
debug('parse error');
freeParser(parser, req);
socket.destroy();
req.emit('error', ret);
req._hadError = true;
}
照这样来看, 走 Socket 应该是行得通的, 只是很麻烦(麻烦到几乎自己要实现部分HTTP协议):
var net = require('net');
var client = net.connect({port: your_port, host:'your_host'},
function() { //'connect' listener
console.log('client connected');
client.write('GET / HTTP/1.1\r\n\r\n'); // 模拟 HTTP请求
});
client.on(‘data’, function(data) {
console.log(data.toString()); // 响应来了, 还要解析 — 工作量巨增
client.end();
});
client.on(‘end’, function() {
console.log(‘client disconnected’);
});
其它方法未知, 可能存在更容易的做法(修改nodejs源码, 再编译?).
20000,蛋疼的状态码。。。
根据你的描述,问题在于服务器返回了一个非标准的状态码(例如20004),而Node.js的http.request
在处理这种非标准状态码时可能会抛出“Parse Error”。
你可以通过捕获错误并处理来解决这个问题。以下是修改后的示例代码:
const http = require('http');
exports.get = function(req, res) {
var data = '<Request><Id>11</Id></Request>';
var opt = {
method: "POST",
host: interfaceConfig.emallServer,
port: interfaceConfig.emallPort,
path: interfaceConfig.emallUser,
headers: {
"Content-Type": 'text/xml',
"Content-Length": Buffer.byteLength(data)
}
};
const request = http.request(opt, function(serverFeedback) {
serverFeedback.setEncoding('utf8');
let responseBody = '';
serverFeedback.on('data', function(chunk) {
responseBody += chunk;
});
serverFeedback.on('end', function() {
console.log(responseBody);
// 在这里处理响应数据
});
});
request.on('error', function(e) {
console.error(`Problem with request: ${e.message}`);
});
request.write(data);
request.end();
};
解释
- 请求配置:确保请求头中的
Content-Length
使用正确的值,使用Buffer.byteLength
而不是直接使用字符串长度。 - 错误处理:通过监听
request
对象的error
事件来捕获并处理错误。 - 响应处理:将响应体拼接起来以便完整地获取响应内容。
这样即使服务器返回一个非标准的状态码,Node.js也不会立即抛出错误,并且你可以根据需要处理响应内容。