Express.js中无法获取POST请求体的问题求助
先贴一下我当前的Express代码:
(function () { 'use strict'; var fs = require('fs'); var cors = require('cors'); var bodyParser = require('body-parser'); var express = require('express'), app = express(), port = 8112; app.use(cors()); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.listen(port); app.route('/abc') .post(abc); function abc(req,res){ console.dir(req.body); res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.sendStatus(200); } })();
现在遇到的问题是:调用这个接口时,req.body打印出来是空对象{},但Chrome的网络面板里明明能看到请求负载。另外POST请求前已经触发了OPTIONS请求,完整请求头信息如下:
POST /abc HTTP/1.1
Host: localhost:8112
Connection: keep-alive
Content-Length: 11
Pragma: no-cache
Cache-Control: no-cache
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
x-api-key:CExkxDlFC35ckfCGX6m61x76GxIYH2h2Iv8bX874
Content-Type:text/plain;charset=UTF-8
Accept: /
Referer: http://localhost:4200/dashboard
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
请求负载内容:
{"dd":"dd"}
问题根源
你看请求头里的Content-Type是text/plain;charset=UTF-8,但当前代码里只配置了bodyParser.urlencoded和bodyParser.json——这两个中间件只会自动解析application/x-www-form-urlencoded和application/json类型的请求体,对text/plain类型的内容完全不会处理,所以req.body才会是空对象。
解决方案
有几个可行的办法,你可以根据实际场景选择:
方案1:添加body-parser的文本解析中间件
在现有bodyParser配置后新增文本解析的中间件,之后手动把解析到的文本转成JSON即可:
// 新增text类型请求的解析中间件 app.use(bodyParser.text({ type: 'text/plain' })); // 修改接口处理函数 function abc(req,res){ // 将解析到的文本转为JSON对象 const requestBody = JSON.parse(req.body); console.dir(requestBody); res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.sendStatus(200); }
方案2:让前端调整请求的Content-Type
如果前端可以修改的话,把请求的Content-Type改成application/json,这样你现有的bodyParser.json()就能自动解析请求体,完全不需要改动后端代码。
方案3:手动监听请求事件解析体
如果不想依赖bodyParser的文本解析,也可以手动监听请求的data和end事件来获取内容:
function abc(req,res){ let rawBody = ''; // 监听数据片段 req.on('data', chunk => { rawBody += chunk.toString(); }); // 数据接收完成后处理 req.on('end', () => { const parsedBody = JSON.parse(rawBody); console.dir(parsedBody); res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.sendStatus(200); }); }
另外提个小优化:你已经配置了cors()中间件,它会自动处理跨域相关的响应头,所以abc函数里手动设置的Access-Control-Allow-Origin等头可以删掉啦,重复配置没必要~
内容的提问来源于stack exchange,提问作者Pradhaban

