网络编程
位置:首页>> 网络编程>> JavaScript>> Express无法通过req.body获取请求传递的数据解决方法

Express无法通过req.body获取请求传递的数据解决方法

作者:shallowdream  发布时间:2024-06-05 09:52:06 

标签:Express,req.body,请求传递,数据获取

前言

最近尝试重新封装XMLHttpRequest,在发post请求的时候,发现express通过req.body获取不到数据,req.body打印出来是一个空对象。

网上也试了网上各种办法,还是不成功,最后发现需要在XMLHttpRequest请求时设置一个请求头,来标识发送过去数据的类型。

1、问题描述

服务端代码如下:创建了一个/login请求,在控制台输出请求数据。

// 创建应用对象
const express = require('express');
const bodyParser = require('body-parser');
// 创建应用对象
const app = express();
app.use((req,res,next)=>{
   //针对跨域进行配置,允许任何源访问
   res.header('Access-Control-Allow-Origin', "*")
   next()
})
// 创建路由规则
app.post("/login", (req,res) =>{
   // 输出req.body
   console.log("req.body:", req.body);
   res.send("login success")
})
// 监听端口启动服务
app.listen(8002,() => {
   console.log("服务已启动,8002端口监听中...");
})

前端代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
   <button id="login">登录</button>
   <script>
       let dom = document.getElementById("login")
       url = "http://localhost:8002/login"
       dom.addEventListener("click",function(){
           let xml = new XMLHttpRequest()
           let data = {"username":"test","password":"123"}
           xml.onreadystatechange = function(){
               if(xml.readyState == 4){
                   console.log(xml.responseText);
               }
           }
           xml.open("post", url , true)
           xml.send(JSON.stringify(data))
       })
   </script>
</body>
</html>

明明已经通过xml.send(JSON.stringify(data))已经将数据转换成json格式传到后端,我们可以打开network查看。

Express无法通过req.body获取请求传递的数据解决方法

但是express中就是获取不到{"username":"test","password":"123"},控制台输出了一个空对象。

Express无法通过req.body获取请求传递的数据解决方法

2、 解决办法

2.1 解决JSON内容格式

查了网上的教程,可以通过引入中间件'body-parser':它是一个HTTP请求体解析中间件,它用于解析客户端请求的body中的内容,如application/x-www-form-urlencodedapplication/json这两种常用的内容格式。

配置后代码如下:

// 创建应用对象
const express = require('express');
// 执行npm install body-parser之后再引入
const bodyParser = require('body-parser');
// 创建应用对象
const app = express();
// 处理application/json内容格式的请求体
app.use(bodyParser.json());
app.use((req,res,next)=>{
   //实验验证,只需要设置这一个就可以进行get请求
   res.header('Access-Control-Allow-Origin', "*")//配置8080端口跨域
   next()
})
// 创建路由规则
app.post("/login", (req,res) =>{
   // console.log(req);
   console.log("req.body:", req.body);
   res.send("login success")
})
// 监听端口启动服务
app.listen(8002,() => {
   console.log("服务已启动,8002端口监听中...");
})

但是依旧获取不到!!!

Express无法通过req.body获取请求传递的数据解决方法

原因:在请求中,没有设置请求头,也就是没有指明你传递的是什么格式的数据,需要通过xml.setRequestHeader("Content-Type","application/json")或者通过xml.setRequestHeader("Content-Type","application/x-www-form-urlencoded");设置请求头中Content-Type值。

前端请求中补充xml.setRequestHeader("Content-Type","application/json")

xml.open("post", url , true)
// 添加Content-Type这个请求头
xml.setRequestHeader("Content-Type","application/json");
xml.send(JSON.stringify(data))

同时在服务端配置跨域请求允许的访问头,如果不配置res.header('Access-Control-Allow-Headers', 'Content-Type'),则会出现以下提示content-type is not allowed

Express无法通过req.body获取请求传递的数据解决方法

跨域配置,配置请求中可携带请求头Content-Type

app.use((req,res,next)=>{
   //针对跨域进行配置,允许任何源访问
   res.header('Access-Control-Allow-Origin', "*")
   // 允许前端请求中包含Content-Type这个请求头
   res.header('Access-Control-Allow-Headers', 'Content-Type')
   next()
})

经过这样配置,即可在服务端成功获取前端传递来的数据:

Express无法通过req.body获取请求传递的数据解决方法

2.2、解决x-www-form-urlencoded内容格式

首先,我们再配置一个获取application/x-www-form-urlencoded内容格式的路由。之后通过配置app.use(bodyParser.urlencoded({extended: false}));即可

服务端代码如下:

// 创建应用对象
const express = require('express');
// 执行npm install body-parser之后再引入
const bodyParser = require('body-parser');
// 创建应用对象
const app = express();
// 处理application/json内容格式的请求体
app.use(bodyParser.json());
// 处理application/x-www-form-urlencoded内容格式的请求体
app.use(bodyParser.urlencoded({extended: false}));
app.use((req,res,next)=>{
   //针对跨域进行配置,允许任何源访问
   res.header('Access-Control-Allow-Origin', "*")
   // 允许前端请求中包含Content-Type这个请求头
   res.header('Access-Control-Allow-Headers', 'Content-Type')
   next()
})
// 创建路由规则
app.post("/login", (req,res) =>{
   // console.log(req);
   console.log("req.body:", req.body);
   res.send("login success")
})
app.post("/login2", (req,res) =>{
   // console.log(req);
   console.log(req.body);
   res.send("login2 success")
})
// 监听端口启动服务
app.listen(8002,() => {
   console.log("服务已启动,8002端口监听中...");
})

前端代码如下:添加了一个登录2按钮,同时绑定了它的请求方法。注意x-www-form-urlencoded这种请求的数据格式为:key=value&key=value

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
   <button id="login">登录</button>
   <button id="login2">登录2</button>
   <script>
       let dom = document.getElementById("login")
       let dom2 = document.getElementById("login2")
       url = "http://localhost:8002/login"
       url2 = "http://localhost:8002/login2"
       dom.addEventListener("click",function(){
           // 创建XMLHttpRequest实例
           let xml = new XMLHttpRequest()
           // 请求体
           let data = {"username":"test","password":"123"}
           xml.onreadystatechange = function(){
               if(xml.readyState == 4){
                   console.log(xml.responseText);
               }
           }
           xml.open("post", url , true)
           xml.setRequestHeader("Content-Type","application/json");
           xml.send(JSON.stringify(data))
       })
       dom2.addEventListener("click",function(){
           // 创建XMLHttpRequest实例
           let xml = new XMLHttpRequest()
           xml.onreadystatechange = function(){
               if(xml.readyState == 4){
                   console.log(xml.responseText);
               }
           }
           xml.open("post", url2 , true)
           xml.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
           xml.send('username=test&password=123')
       })
   </script>
</body>
</html>

如下图所示:可见数据已经发送到后端。

Express无法通过req.body获取请求传递的数据解决方法

同时,后端可以通过req.body成功获取到数据。

Express无法通过req.body获取请求传递的数据解决方法

但是数据前面有一个Object: null prototype,这个是不影响取值的,按照上面这个例子,我们依旧可以通过req.body.usernamereq.body.password获取到对应的数据。

app.post("/login2", (req,res) =>{
   // console.log(req);
   console.log(req.body);
   console.log(req.body.username);
   console.log(req.body.password);
   res.send("login2 success")
})

Express无法通过req.body获取请求传递的数据解决方法

当然,我们也可以通过先对对象进行JSON字符串转化JSON.stringify(),然后再转化成对象JSON.parse(),这样就可以将其去除了。

app.post("/login2", (req,res) =>{
   console.log(JSON.parse(JSON.stringify(req.body)));
   res.send("login2 success")
})

Express无法通过req.body获取请求传递的数据解决方法

3、附

3.1、获取get请求参数

通过req.query来获取get请求参数

服务端代如下:我们再配置一个/data的路由。

// 创建路由规则
app.get('/data',(req,response) => {
   let obj = {
       name:'test',
       age:18
   }
   console.log(req.query);
   response.send(obj)
});
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>
<body>
   <button id="login">登录</button>
   <button id="login2">登录2</button>
   <button id="getinfo">获取数据</button>
   <script>
       let dom = document.getElementById("login")
       let dom2 = document.getElementById("login2")
       let dom3 = document.getElementById("getinfo")
       url = "http://localhost:8002/login"
       url2 = "http://localhost:8002/login2"
       // get请求中参数是放在url中
       url3 = "http://localhost:8002/data?id=3"
       dom.addEventListener("click",function(){
           // 创建XMLHttpRequest实例
           let xml = new XMLHttpRequest()
           // 请求体
           let data = {"username":"test","password":"123"}
           xml.onreadystatechange = function(){
               if(xml.readyState == 4){
                   console.log(xml.responseText);
               }
           }
           xml.open("post", url , true)
           xml.setRequestHeader("Content-Type","application/json");
           xml.send(JSON.stringify(data))
       })
       dom2.addEventListener("click",function(){
           // 创建XMLHttpRequest实例
           let xml = new XMLHttpRequest()
           xml.onreadystatechange = function(){
               if(xml.readyState == 4){
                   console.log(xml.responseText);
               }
           }
           xml.open("post", url2 , true)
           xml.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
           xml.send('username=test&password=123')
       })
       dom3.addEventListener("click",function(){
           // 创建XMLHttpRequest实例
           let xml = new XMLHttpRequest()
           xml.onreadystatechange = function(){
               if(xml.readyState == 4){
                   console.log(xml.responseText);
               }
           }
           xml.open("get", url3 , true)
           // get请求参数是放在url中,而不是通过xml.send()发送过去,不可以使用以下写法:xml.send("id=3")
           xml.send()
       })
       // console.log(a);
       // let a = 1
   </script>
</body>
</html>

成功通过req.query获取到get的请求参数

Express无法通过req.body获取请求传递的数据解决方法

3.2、封装XMLHttpRequest

上面的请求代码太冗余,写了好多let xml = new XMLHttpRequest()、xml.open()、xml.send()等。我的本意是想着封装一下XMLHttpRequest,碰巧遇到了这个post参数取不到的问题。现在回到最开始,对XMLHttpRequest做一个简单的封装吧。

ajax.js代码如下:

(function () {
   const AJAX = function (options) {
       try {
           // 1、解析参数
           var method = options.method
           var url = options.url
           var data = options.data
           var contentType = options.contentType || "json"
           var headers = options.headers
           var async = options.async || false
           var successCallback = options.successCallback || function () { }
           var errorCallback = options.errorCallback || function (err) { console.log(err); }
       } catch (err) {
           console.log("Parsing parameter error")
       }
       try {
           // 2、创建XMLHttpRequest或ActiveXObject对象
           var xhr = null
           if (window.XMLHttpRequest) {
               xhr = new XMLHttpRequest()
           } else {
               // 兼容IE6, IE5
               xhr = new ActiveXObject("Microsoft.XMLHTTP");
           }
           // 3、设置get请求参数
           if (method == "get") {
               var params = ""
               if (data) {
                   for (v in data) {
                       params += v + "=" + data[v] + "&"
                   }
                   params = params.replace(/&$/, "");
                   xhr.open(method, url + "?" + params, async)
                   xhr.send()
               } else {
                   xhr.open(method, url, async)
                   xhr.send()
               }
           } else if (method == "post") {
               // 设置post请求参数
               xhr.open(method, url, async)
               if (contentType == "application/x-www-form-urlencoded; charset=UTF-8") {
                   xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
               } else if (contentType == "application/json") {
                   xhr.setRequestHeader("Content-Type", "application/json");
               }
               xhr.send(JSON.stringify(data))
           }
           // 设置请求头
           if (headers) {
               for (h in headers) {
                   if (h == "Content-Type") {
                       continue
                   }
                   xhr.setRequestHeader(h, headers.h)
               }
           }
           xhr.onreadystatechange = function () {
               // 成功回调
               if (xhr.readyState == 4 && xhr.status == 200) {
                   successCallback()
               }
           }
           xhr.onerror = function (err) {
               // 失败回调
               errorCallback(err);
           }
           return xhr.response
       } catch (err) {
           console.log("Request Error");
       }
   }
   // 将AJAX对象暴露到window对象上
   window.AJAX = AJAX
})(window)

html代码:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
   <script src="../ajax.js"></script>
</head>
<body>
   <button id="login">登录</button>
   <button id="login2">登录2</button>
   <button id="getinfo">获取数据</button>
   <script>
       let dom = document.getElementById("login")
       let dom2 = document.getElementById("login2")
       let dom3 = document.getElementById("getinfo")
       url = "http://localhost:8002/login"
       url2 = "http://localhost:8002/login2"
       url3 = "http://localhost:8002/data?id=3"
       dom.addEventListener("click",function(){
           let options = {
               method:"post",
               url:"http://localhost:8002/login",
               data:{"username":"test","password":"123"},
               contentType:"application/json"
           }
           let res = AJAX(options)
           console.log("res", res);
       })
       dom2.addEventListener("click",function(){
           let options = {
               method:"post",
               url:"http://localhost:8002/login2",
               data:{"username":"test","password":"123"},
               contentType:"application/x-www-form-urlencoded; charset=UTF-8"
           }
           let res = AJAX(options)
           console.log("res", res);
       })
       dom3.addEventListener("click",function(){
           let options = {
               method:"get",
               url:"http://localhost:8002/data",
               data:{"id": 1}
           }
           let res = AJAX(options)
           console.log("res", res);
       })
   </script>
</body>
</html>

4、总结

首先分析了req.body获取不到数据的原因,之后给出了解决办法,通过设置响应头、使用中间件、配置跨域请求这三种方式来解决获取不到数据的问题。最后简单的封装了XMLHttpRequest

来源:https://juejin.cn/post/7173186357643182093

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com