背景
node作为中间层调用后端java服务端接口。
问题
curl请求后端接口报错ResponseError: Parse Error。没有超时,因为是立即返回的,直接报错了。不是每个接口都会报错,只有一两个接口会报错。部署到linux服务器上报错,本地不报错。而且在linux服务器上直接用curl命令发起请求看到服务端是正常返回的。
报错信息如下:
ResponseError: Parse Error, POST http://10.16.70.183:9104/xres-rms/service/rs/v1/deviceService/save -1 (connected: true, keepalive socket: false, agent status: {"createSocketCount":20,"createSocketErrorCount":0,"closeSocketCount":19,"errorSocketCount":0,"timeoutSocketCount":18,"requestCount":29,"freeSockets":{},"sockets":{"10.16.70.183:9104:":1},"requests":{}}, socketHandledRequests: 1, socketHandledResponses: 0)
headers: {}
at Socket.socketOnData (_http_client.js:452:22)
at Socket.emit (events.js:200:13)
at addChunk (_stream_readable.js:294:12)
at readableAddChunk (_stream_readable.js:275:11)
at Socket.Readable.push (_stream_readable.js:210:10)
at TCP.onStreamRead (internal/stream_base_commons.js:166:17)
排查步骤
- 是否是服务器的设置问题。
- 列表项目
在服务器上用命令curl发起请求,看是否正常。curl发起请求的命令如下
curl -X POST \
http://10.19.132.127:9104/xres-rms/service/rs/v1/deviceService/save \
-H 'Content-Type: application/json' \
-H 'Postman-Token: 4b9c514b-2444-4f3e-850c-2629987fcac4' \
-H 'TOKEN: SElLIDBPUENpUGNPZm5JNkVQbDQ6N3pHaTNmcWJxNnFIRWdEeTh5dTZ2ZmpWb1NMZi9uaUNFTWY2cE11ZHFTWT06MTU2NjYxNTQ4NDA5Ng==' \
-H 'cache-control: no-cache' \
-d '{ "resourceType": "ENCODE_DEVICE",
"externalIndexCode": "10000000001320939591",
"userPwd": "EQAQAODkw0AuqpGM21fuUtkYDOzQfnlKYi7FWLSSSOYtjwexwFAmeienXbEF4BkFWyaOjA==",
"treatyType": "hiksdk_net",
"netZoneId": 0,
"manufacturer": "hikvision",
"tag": "@@",
"tagPath": "$$",
"addType": 1,
"networkAddr": "1.1.6.1",
"networkPort": 8001,
"userName":"admin",
"belongIndexCode": "",
"deviceClass": "100001",
"analogChanCount": 0,
"digitalChanCount": 0,
"alarmInCount": 0,
"alarmOutCount": 0,
"regionIndexCode": "ed87743033f3459f814edaf1cc0d4420",
"deviceCategory": "vss",
"pwdStrength": 3 }'
可以看出不是服务器的设置问题,应该是代码问题。既然不是代码问题,先抓包看看数据分析一下。
- 用tcpdump抓包看请求
打开linux服务器,输入以下命令:
tcpdump -i eth0 '((tcp) and (port 9104) and (dst host 10.19.132.127))' -w out.cap
抓取发送到10.19.132.127,端口是9104的所有tcp请求,并输出并保存到out.cap文件 eth0表示网卡,查询网卡用命令
ip a
- 用wireshark打开请求的接口,查看详情
可以看出没有收到response
看下正常的response是这样的
是会有个response in frame的。
可以确定确实没有收到response。
但是em...为什么node版本是12.4??最新的稳定版本明明是10.16.3啊。。可以看node官网查看最新版本是12.9.1,为了验证我的猜想,我安装了最新的12.9.1的版本,于是本地接口也报错了
ResponseError: Parse Error: Invalid header value char, POST http://10.19.132.127:8020/xres-res/service/rs/resourceOrgRestService/v1/batchDeleteResourceOrg -1 (connected: true, keepalive socket: true, agent status: {"createSocketCount":6,"createSocketErrorCount":0,"closeSocketCount":5,"errorSocketCount":0,"timeoutSocketCount":5,"requestCount":12,"freeSockets":{},"sockets":{"10.19.132.127:8020:":1},"requests":{}}, socketHandledRequests: 4, socketHandledResponses: 3)
headers: {}
at Socket.socketOnData (_http_client.js:456:22)
at Socket.emit (events.js:209:13)
at addChunk (_stream_readable.js:305:12)
at readableAddChunk (_stream_readable.js:286:11)
at Socket.Readable.push (_stream_readable.js:220:10)
at TCP.onStreamRead (internal/stream_base_commons.js:166:17)
这里非常明显的看到了错误原因
ResponseError: Parse Error: Invalid header value char
响应头解析失败。打断点查看响应头,把本地的node版本改回稳定版本10.16.3,看到的数据如下
{ notation: '@\tѧ¹òsTvÖDÖsTsû\u000eÍ° dѧ¹',
span_id: '78f9edd00a134b5d8c4b4bc3c35dd1bf',
date: 'Mon, 26 Aug 2019 06:07:51 GMT',
connection: 'keep-alive',
'content-type': 'application/json',
'content-length': '134',
'x-application-context': 'xres-res:dev:8020',
trace_id: '682033d4866c4438b26978cce00c4520',
code: '0x08f70038' }
可以看到notation这里乱码了,导致了解析失败。
结论
node12用了新的http-parser,所以对响应头的要求更严格了,导致了解析失败~
用最新版的node需谨慎,现在都还是踩坑的阶段~~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。