Express無法通過req.body獲取請求傳遞的數(shù)據(jù)解決方法
前言
最近嘗試重新封裝XMLHttpRequest,在發(fā)post請求的時候,發(fā)現(xiàn)express通過req.body獲取不到數(shù)據(jù),req.body打印出來是一個空對象。
網上也試了網上各種辦法,還是不成功,最后發(fā)現(xiàn)需要在XMLHttpRequest請求時設置一個請求頭,來標識發(fā)送過去數(shù)據(jù)的類型。
1、問題描述
服務端代碼如下:創(chuàng)建了一個/login請求,在控制臺輸出請求數(shù)據(jù)。
// 創(chuàng)建應用對象
const express = require('express');
const bodyParser = require('body-parser');
// 創(chuàng)建應用對象
const app = express();
app.use((req,res,next)=>{
//針對跨域進行配置,允許任何源訪問
res.header('Access-Control-Allow-Origin', "*")
next()
})
// 創(chuàng)建路由規(guī)則
app.post("/login", (req,res) =>{
// 輸出req.body
console.log("req.body:", req.body);
res.send("login success")
})
// 監(jiān)聽端口啟動服務
app.listen(8002,() => {
console.log("服務已啟動,8002端口監(jiān)聽中...");
})
前端代碼如下:
<!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))已經將數(shù)據(jù)轉換成json格式傳到后端,我們可以打開network查看。

但是express中就是獲取不到{"username":"test","password":"123"},控制臺輸出了一個空對象。

2、 解決辦法
2.1 解決JSON內容格式
查了網上的教程,可以通過引入中間件'body-parser':它是一個HTTP請求體解析中間件,它用于解析客戶端請求的body中的內容,如application/x-www-form-urlencoded、application/json這兩種常用的內容格式。
配置后代碼如下:
// 創(chuàng)建應用對象
const express = require('express');
// 執(zhí)行npm install body-parser之后再引入
const bodyParser = require('body-parser');
// 創(chuàng)建應用對象
const app = express();
// 處理application/json內容格式的請求體
app.use(bodyParser.json());
app.use((req,res,next)=>{
//實驗驗證,只需要設置這一個就可以進行get請求
res.header('Access-Control-Allow-Origin', "*")//配置8080端口跨域
next()
})
// 創(chuàng)建路由規(guī)則
app.post("/login", (req,res) =>{
// console.log(req);
console.log("req.body:", req.body);
res.send("login success")
})
// 監(jiān)聽端口啟動服務
app.listen(8002,() => {
console.log("服務已啟動,8002端口監(jiān)聽中...");
})
但是依舊獲取不到!??!

原因:在請求中,沒有設置請求頭,也就是沒有指明你傳遞的是什么格式的數(shù)據(jù),需要通過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'),則會出現(xiàn)以下提示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()
})
經過這樣配置,即可在服務端成功獲取前端傳遞來的數(shù)據(jù):

2.2、解決x-www-form-urlencoded內容格式
首先,我們再配置一個獲取application/x-www-form-urlencoded內容格式的路由。之后通過配置app.use(bodyParser.urlencoded({extended: false}));即可
服務端代碼如下:
// 創(chuàng)建應用對象
const express = require('express');
// 執(zhí)行npm install body-parser之后再引入
const bodyParser = require('body-parser');
// 創(chuàng)建應用對象
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()
})
// 創(chuàng)建路由規(guī)則
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")
})
// 監(jiān)聽端口啟動服務
app.listen(8002,() => {
console.log("服務已啟動,8002端口監(jiān)聽中...");
})
前端代碼如下:添加了一個登錄2按鈕,同時綁定了它的請求方法。注意x-www-form-urlencoded這種請求的數(shù)據(jù)格式為: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(){
// 創(chuàng)建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(){
// 創(chuàng)建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>
如下圖所示:可見數(shù)據(jù)已經發(fā)送到后端。

同時,后端可以通過req.body成功獲取到數(shù)據(jù)。

但是數(shù)據(jù)前面有一個Object: null prototype,這個是不影響取值的,按照上面這個例子,我們依舊可以通過req.body.username與req.body.password獲取到對應的數(shù)據(jù)。
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請求參數(shù)
通過req.query來獲取get請求參數(shù)
服務端代如下:我們再配置一個/data的路由。
// 創(chuàng)建路由規(guī)則
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">獲取數(shù)據(jù)</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請求中參數(shù)是放在url中
url3 = "http://localhost:8002/data?id=3"
dom.addEventListener("click",function(){
// 創(chuàng)建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(){
// 創(chuàng)建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(){
// 創(chuàng)建XMLHttpRequest實例
let xml = new XMLHttpRequest()
xml.onreadystatechange = function(){
if(xml.readyState == 4){
console.log(xml.responseText);
}
}
xml.open("get", url3 , true)
// get請求參數(shù)是放在url中,而不是通過xml.send()發(fā)送過去,不可以使用以下寫法:xml.send("id=3")
xml.send()
})
// console.log(a);
// let a = 1
</script>
</body>
</html>
成功通過req.query獲取到get的請求參數(shù)

3.2、封裝XMLHttpRequest
上面的請求代碼太冗余,寫了好多let xml = new XMLHttpRequest()、xml.open()、xml.send()等。我的本意是想著封裝一下XMLHttpRequest,碰巧遇到了這個post參數(shù)取不到的問題。現(xiàn)在回到最開始,對XMLHttpRequest做一個簡單的封裝吧。
ajax.js代碼如下:
(function () {
const AJAX = function (options) {
try {
// 1、解析參數(shù)
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、創(chuàng)建XMLHttpRequest或ActiveXObject對象
var xhr = null
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest()
} else {
// 兼容IE6, IE5
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
// 3、設置get請求參數(shù)
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請求參數(shù)
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">獲取數(shù)據(jù)</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獲取不到數(shù)據(jù)的原因,之后給出了解決辦法,通過設置響應頭、使用中間件、配置跨域請求這三種方式來解決獲取不到數(shù)據(jù)的問題。最后簡單的封裝了XMLHttpRequest。
以上就是Express無法通過req.body獲取請求傳遞的數(shù)據(jù)解決方法的詳細內容,更多關于Express req.body請求傳遞的資料請關注腳本之家其它相關文章!
- node.js使用express-jwt報錯:expressJWT?is?not?a?function解決
- 解決React報錯Expected an assignment or function call and instead saw an expression
- React報錯信息之Expected?an?assignment?or?function?call?and?instead?saw?an?expression
- MySQL運行報錯:“Expression?#1?of?SELECT?list?is?not?in?GROUP?BY?clause?and?contains?nonaggre”解決方法
- 解決三元運算符 報錯“SyntaxError: can''''t assign to conditional expression”
- 解決大于5.7版本mysql的分組報錯Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated
- express框架,報錯:“Cannot set headers after they are sent to the client”,解決方法總結
相關文章
JavaScript indexOf的第二個參數(shù)用法
indexOf 是我們非常熟悉的一個方法,它可以用來獲取某一個元素在一個數(shù)組里的位置,我們一般就會使用 array.indexOf(element) 的方法來進行使用,但是,大家有沒有使用過 indexOf 的第二個參數(shù)呢?本文將給大家介紹一下indexOf的第二個參數(shù)用法,需要的朋友可以參考下2024-02-02
js獲取url中的參數(shù)且參數(shù)為中文時通過js解碼
這篇文章主要介紹了url中傳遞中文參數(shù)的時候通過js解碼,需要的朋友可以參考下2014-03-03
JavaScript實現(xiàn)選中文字提示新浪微博分享效果
這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)選中文字提示新浪微博分享效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06
JavaScript 就地編輯HTML節(jié)點實現(xiàn)代碼
JavaScript 就地編輯HTML節(jié)點實現(xiàn)代碼2009-07-07
js實現(xiàn)固定顯示區(qū)域內自動縮放圖片的方法
這篇文章主要介紹了js實現(xiàn)固定顯示區(qū)域內自動縮放圖片的方法,實例分析了javascript操作頁面元素及屬性的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07
使用contextMenu插件實現(xiàn)Bootstrap table彈出右鍵菜單
如今Bootstrap這個前端框架已被許多人接受并應用在不同的項目中,其中“開發(fā)高效,設備兼容”的特點表現(xiàn)得非常明顯。這篇文章主要介紹了使用contextMenu插件實現(xiàn)Bootstrap table彈出右鍵菜單,需要的朋友可以參考下2017-02-02

