Express无法通过req.body获取请求传递的数据解决方法
作者:shallowdream 发布时间:2024-06-05 09:52:06
前言
最近尝试重新封装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
。
来源:https://juejin.cn/post/7173186357643182093
猜你喜欢
- 1.变量的赋值操作只是多生成了一个变量,实际上还是指向同一个对象# -*- coding: utf-8 -*-class CPU: &nbs
- 在Python里面,使用Pandas里面的DataFrame来存放数据的时候想要把数据集进行shuffle会许多的方法,本文介绍两种比较常用
- 本篇主要将react全家桶的产品非常精炼的提取了核心内容,精华程度堪比精油。各位大人,既然来了,客官您坐,来人,给客官看茶~~redux前言
- 本文实例讲述了Symfony2框架创建项目与模板设置的方法。分享给大家供大家参考,具体如下:环境准备与概览习惯于在windows使用netb
- 环境准备好了!我们怎么使用这些东东?IIS用组件初始化是用这个过程Public Sub OnStartPage给个使用asp组件的例子:数字
- 数据安全是任何数据服务解决方案中的一个关键要求,而Windows Server 2008和SQL Server 2008结合起来,通过一个基
- 从技术上来说,在ASP环境中,读入并管理XML文本的主要方法有三种: 创建MSXML对象,并且将XML文档载入DOM; 使用服务器端嵌入(S
- 子查询-嵌套查询子查询是指一个查询语句嵌套在另一个语句内部的查询原始查询方法SELECT last_name,salaryFROM empl
- 但是,具有identity特性的字段,不需要具有唯一性,更不必须是主键。 可以通过,set identity_insert tablenam
- 把程序放到一个文件中,然后包含再call就可以了。(JMAIL4.3)<%'警告函数sub w_msg(messag
- 本文实例讲述了微信小程序开发之animation循环动画实现的让云朵飘效果。分享给大家供大家参考,具体如下:微信小程序提供了实现动画的api
- 前言props指父组件往子组件中传入参数,我们来介绍下如何理解vue3的props的原理介绍了解其原理之前我们要清楚vue的虚拟节点是什么,
- 本文实例讲述了Python实现的计算器功能。分享给大家供大家参考,具体如下:源码:# -*- coding:utf-8 -*-#! pyth
- Django中上传文件方式。如何实现文件上传功能?1创建项目uploadfile:创建app:front项目设置INSTALLED_APPS
- 这篇文章主要介绍了Python实现结构体代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以
- 本文实例为大家分享了Python实现图书馆座位自动预约的具体代码,供大家参考,具体内容如下配置通过公网主机定时运行脚本,并发送邮件到自己的q
- TensorFlow 定义输入节点名称input_name: with tf.name_scope('input'): &
- 经常需要读取某个文件夹下所有的图像文件。我使用python写了个简单的代码,读取某个文件夹下某个后缀的文件,将文件名生成为文本(csv格式)
- 背景测试工具箱写到一半,今天遇到了一个前后端数据交互的问题,就一起做一下整理。环境-----------------------------
- 在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器、迭代器和生成器理解进行