node后端接收到axios的post请求体为空???
使用axios发送post请求,传入了Object格式的参数,在node后端req.body接收到的参数为空,但是网页上抓包检查时,发现请求的body确实是携带了参数的?
后端使用了express搭建服务器,并使用了cors解决前端请求跨域问题,于是我开始了漫长的debug。首先,我使用中间件,在数据提交到后台时,先在控制台打印一下req.body这个对象
node.js 中部分代码
vue中部分代码
显而易见,服务器中req.body请求体中没有任何参数。但是页面确实是提交了数据呀?于是我在页面F12进行网络抓包来查看发出去的request请求
抓到的包中请求体确实携带了页面发送的参数,然后我就开始意识到事情的不对劲了,开始在网上搜索答案。后来,我把问题锁定到了axios请求机制和服务器对请求体数据解析上,之后尝试过在axios请求函数中,在header中配置内容数据格式为’Content-Type’: ‘application/x-www-form-urlencoded’,依然没用。经过漫长的网上冲浪,并查了一下axios的源码,我发现axios的文档上有这样一句话
这就能解释为什么我之前发obj对象数据,请求体携带的确是json格式的数据,说明axios会自动转换数据为json格式后来我又在源码上看到了转换请求体参数格式的相关代码
if(utils.isURLSearchParams(data){
setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded');
return data.tostring();
}
if(utils.isObject(data){
setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
return JSON.stringfy(data);
}
显然,axios在发送请求时,如果参数对象data不是表单数据格式对象,就会默认把数据转为json字符串,放到请求体中的。所以我之前发过去的obj对象,被axios自动转化为了json字符串,但是将JSON字符串格式的参数发给服务器,应该也没什么问题呀?于是我就重新回到服务器的配置代码上来,显然,应该是服务器无法解析request请求的请求体body中JSON字符串的数据。这让我想到了我最开始配置的这行代码。
// 配置解析 数据格式为表单数据的请求体 的中间件
app.use(express.urlencoded({ extended: false }))
expres服务器默认无法解析数据格式为表单数据的请求体,因此express才提供了这个中间件,让我们配置,从而能够解析req.body 中表单格式数据。而这个中间件内部,其实是在配置body-parser属性,所以我的每个request请求都是要经过这个过滤器解析的,也就是说,这个中间件不能解析json格式字符串????
经过网上查阅,我找到了如下解释
body-parser的urlencoded方法顾名思义就是把传来的数据当做url来处理,也就是像querystring一样,所以对于传过来的json数据,没有识别到切割key和value的标志,就把所有都当做key来处理
body-parser无法解析请求体中的JSON字符串,所以当收到JSON格式的参数时,因无法解析,所以req.body就为空了
解决: 1:既然body-parser只能解析序列化的表单数据格式,即“?username=username&time=time&textdata=textdata&imgUrl=imgUrl”我们只要将参数对象序列化成表单数据格式,再发送就好了。
这里要用到axios提供的 qs 库,qs是axios自带的一个库 功能:
里面的stringify方法可以将一个json对象直接转为(以?和&符连接的形式)。 在开发中,发送请求的入参大多是一个对象。在发送时,如果该请求为get请求,就需要对参数进行转化。使用该库,就可以自动转化,而不需要手动去拼接,所以我只要将我的参数对象通过qs的stringfy方法转换为表单数据格式,再通过axios发送给服务器,body-parser就能解析成key,value的键值对形式,放入req.body中。
2:在node中配置body-parser可以获取到除formdata之外的数据
3:在node中配置connect-multiparty可以所有数据
vue中使用axios发送post请求