今日发现生产环境里部署的日志报错,报404,提示程序错误
这是一个使用koa搭建的nodejs接口服务,接收一个长文本解析成发货省市区地址信息
片段代码如下:
router.post("/resolution", async (ctx, next) => {
const queryInfo = decodeURIComponent(ctx.request.body['Content']);
//………………
});
报错日志是这么写的
server error URIError: URI malformed
at decodeURIComponent (<anonymous>)
at D:\workspace\project\routes\address.js:7:23
at dispatch (D:\workspace\project\node_modules\koa-compose\index.js:44:32)
at next (D:\workspace\project\node_modules\koa-compose\index.js:45:18)
at D:\workspace\project\node_modules\koa-router\lib\router.js:346:16
at dispatch (D:\workspace\project\node_modules\koa-compose\index.js:44:32)
at D:\workspace\project\node_modules\koa-compose\index.js:36:12
at dispatch (D:\workspace\project\node_modules\koa-router\lib\router.js:351:31)
at dispatch (D:\workspace\project\node_modules\koa\node_modules\koa-compose\index.js:42:32)
at dispatch (D:\workspace\project\node_modules\koa-router\lib\router.js:332:32)
at dispatch (D:\workspace\project\node_modules\koa\node_modules\koa-compose\index.js:42:32)
at dispatch (D:\workspace\project\node_modules\koa-router\lib\router.js:332:32)
at dispatch (D:\workspace\project\node_modules\koa\node_modules\koa-compose\index.js:42:32)
at D:\workspace\project\app.js:45:9
at dispatch (D:\workspace\project\node_modules\koa\node_modules\koa-compose\index.js:42:32)
at views (D:\workspace\project\node_modules\koa-views\src\index.js:91:12) {
request: {
method: 'POST',
url: '/address/resolution',
header: {
'user-agent': '……………………',
'content-type': 'application/json',
accept: '*/*',
host: '……………………',
'accept-encoding': 'gzip, deflate, br',
connection: 'keep-alive',
'content-length': '270'
}
},
response: {
status: 404,
message: 'Not Found',
header: [Object: null prototype] {
vary: 'Origin',
'access-control-allow-origin': '*',
'access-control-expose-headers': 'WWW-Authenticate,Server-Authorization'
}
},
app: { subdomainOffset: 2, proxy: false, env: 'development' },
originalUrl: '/address/resolution',
req: '<original node req>',
res: '<original node res>',
socket: '<original node socket>'
}
上来就被误导了,前几天刚解决掉 content-type的问题,以为调用端有代码没改,检查了一圈,发现content的内容是:
山东省青岛市黄岛区 龙山街道王子山路迢兴科技5号仓库,原装鞋盒外禁缠胶带!退换在原鞋盒外套快递加固箱退回,损坏影响二次销售按订单金额40%赔付或严重拒收,拒收到付件和百世!
用 decodeURIComponent 在浏览器控制台试了一下这个,报一样的错:URI malformed
我以为是接口404是咋了呢?立马定位到这句话里面的那个40%
经过考察一些资料得知,原来decodeURIComponent 不是像普通字符串处理函数一下随便用的,里面会对一些传参字符串做转译,如:%、&、#、=
而这个%是汉字转译的开头,就发生了这个错误
那既然知道这个问题,解决办法就简单了,转成能让他认的字符不就好了?
写一个转换方法,对这四个字符做转换,然后再使用
function encodeContent(key) {
const encodeArr = [{
code: '%',
encode: '%25'
}, {
code: '?',
encode: '%3F'
}, {
code: '#',
encode: '%23'
}, {
code: '&',
encode: '%26'
}, {
code: '=',
encode: '%3D'
}];
return key.replace(/[%?#&=]/g, ($, index, str) => {
for (const k of encodeArr) {
if (k.code === $) {
return k.encode;
}
}
});
}
// 然后这样,就行啦!
const queryInfo = decodeURIComponent(encodeContent(ctx.request.body['Content']));
总结,平时看起来没问题的函数,在实际应用中不知道会传进来什么东西,这个decodeURIComponent以后用之前要考虑数据进来的途径,需谨慎😓
处理接收数据的时候,要注意将数据转换下,避免导致函数返回异常