Express无法通过req.body获取请求传递的数据解决方法
shallowdream 人气:0前言
最近尝试重新封装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
中就是获取不到{"username":"test","password":"123"}
,控制台输出了一个空对象。
2、 解决办法
2.1 解决JSON内容格式
查了网上的教程,可以通过引入中间件'body-parser'
:它是一个HTTP
请求体解析中间件,它用于解析客户端请求的body
中的内容,如application/x-www-form-urlencoded
、application/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端口监听中..."); })
但是依旧获取不到!!!
原因:在请求中,没有设置请求头,也就是没有指明你传递的是什么格式的数据,需要通过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
。
跨域配置,配置请求中可携带请求头Content-Type
app.use((req,res,next)=>{ //针对跨域进行配置,允许任何源访问 res.header('Access-Control-Allow-Origin', "*") // 允许前端请求中包含Content-Type这个请求头 res.header('Access-Control-Allow-Headers', 'Content-Type') next() })
经过这样配置,即可在服务端成功获取前端传递来的数据:
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>
如下图所示:可见数据已经发送到后端。
同时,后端可以通过req.body
成功获取到数据。
但是数据前面有一个Object: null prototype
,这个是不影响取值的,按照上面这个例子,我们依旧可以通过req.body.username
与req.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") })
当然,我们也可以通过先对对象进行JSON
字符串转化JSON.stringify()
,然后再转化成对象JSON.parse()
,这样就可以将其去除了。
app.post("/login2", (req,res) =>{ console.log(JSON.parse(JSON.stringify(req.body))); res.send("login2 success") })
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
的请求参数
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
。
加载全部内容