我有这个作为我的快速服务器的配置
app.use(app.router);
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
app.set('view engine', 'ejs');
app.set("view options", { layout: true });
//Handles post requests
app.use(express.bodyParser());
//Handles put requests
app.use(express.methodOverride());
但是当我在我的路由中请求req.body.something时,我得到了一些错误,指出body是未定义的。下面是一个使用req的路由示例。身体:
app.post('/admin', function(req, res){
console.log(req.body.name);
});
我读到这个问题是由缺乏app.use(express.bodyParser())引起的;但你可以看到,我把它叫做路线之前。
有线索吗?
2020年7月更新
express. bodyparser()不再捆绑为express的一部分。你需要在加载前单独安装:
npm i body-parser
// then in your app
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// create application/json parser
var jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
res.send('welcome, ' + req.body.username)
})
// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
// create user in req.body
})
更多信息请看这里
原来是
在定义路由之前必须确定所有的配置。如果这样做,就可以继续使用express.bodyParser()。
举例如下:
var express = require('express'),
app = express(),
port = parseInt(process.env.PORT, 10) || 8080;
app.configure(function(){
app.use(express.bodyParser());
});
app.listen(port);
app.post("/someRoute", function(req, res) {
console.log(req.body);
res.send({ status: 'SUCCESS' });
});
看来express不再附带body解析器了。我们可能要单独安装。
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
// parse application/vnd.api+json as json
app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
app.use(function (req, res, next) {
console.log(req.body) // populated!
更多信息和示例请参阅git页面https://github.com/expressjs/body-parser。
根据@kevin-xue所说,需要声明内容类型。在我的实例中,这只发生在IE9中,因为XDomainRequest不设置内容类型,所以bodyparser和expressjs忽略了请求的主体。
我通过在将请求传递给主体解析器之前显式地设置content-type来解决这个问题,如下所示:
app.use(function(req, res, next) {
// IE9 doesn't set headers for cross-domain ajax requests
if(typeof(req.headers['content-type']) === 'undefined'){
req.headers['content-type'] = "application/json; charset=UTF-8";
}
next();
})
.use(bodyParser.json());
感谢@spikeyang的精彩回答(如下所示)。在阅读了这篇文章后,我决定分享我的解决方案。
什么时候使用?
解决方案要求你使用快速路由器才能享受它。所以:
如果你试图使用已接受的答案,但运气不好,只需使用复制粘贴这个函数:
function bodyParse(req, ready, fail)
{
var length = req.header('Content-Length');
if (!req.readable) return fail('failed to read request');
if (!length) return fail('request must include a valid `Content-Length` header');
if (length > 1000) return fail('this request is too big'); // you can replace 1000 with any other value as desired
var body = ''; // for large payloads - please use an array buffer (see note below)
req.on('data', function (data)
{
body += data;
});
req.on('end', function ()
{
ready(body);
});
}
叫它:
bodyParse(req, function success(body)
{
}, function error(message)
{
});
注意:
对于大的有效载荷-请使用数组缓冲区(更多@ MDN)
浪费了很多时间:
这取决于客户端请求中的Content-Type
服务器应该有不同的,以下app.use()之一:
app.use(bodyParser.text({ type: 'text/html' }))
app.use(bodyParser.text({ type: 'text/xml' }))
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))
app.use(bodyParser.json({ type: 'application/*+json' }))
来源:https://www.npmjs.com/package/body-parser bodyparsertextoptions
例子:
对我来说,
在客户端,我有以下标题:
Content-Type: "text/xml"
因此,在服务器端,我使用:
app.use(bodyParser.text({type: 'text/xml'}));
然后,要求。身体工作正常。
以防有人遇到和我一样的问题;我使用一个url前缀像
http://example.com/api/
哪一个是用路由器设置的
app.use('/api', router);
然后我有了以下内容
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
修复我的问题是将bodyparser配置放在app.use('/api', router)之上;
最后
// setup bodyparser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//this is a fix for the prefix of example.com/api/ so we dont need to code the prefix in every route
app.use('/api', router);
我的是一个文本输入,我在这里添加了这个答案,所以它会帮助人们。确保在解析时设置了编码!我努力让它工作,直到我给它设置了一个合适的值。
这是我在没有使用任何解析器的情况下得到的错误:
error info: TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object.
Received an instance of undefined at Function.from (buffer.js:327:9)
我们现在不必像其他人已经提到的那样在Express中使用body解析器,而只需使用app.use(Express .text());没能解决我的问题。
undefined现在变成了Object。根据Express文档,如果Content-Type不匹配(在其他情况下),请求主体将返回一个空对象({})。
error info: TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object.
Received an instance of Object at Function.from (buffer.js:327:9)
您设置的编码类型也需要正确。在我的例子中,它是文本/纯文本。您可以更改它以满足您的需要,如JSON等。我这样做了,瞧!效果好极了!
app.use(express.text({
type: "text/plain"
}));
简单的例子,通过所有:
方法='post'登录后的快捷代码:
这将不需要任何这样的bodyParser()。
app.js
const express = require('express');
const mongoose = require('mongoose');
const mongoDB = require('mongodb');
const app = express();
app.set('view engine', 'ejs');
app.get('/admin', (req,res) => {
res.render('admin');
});
app.post('/admin', (req,res) => {
console.log(JSON.stringify(req.body.name));
res.send(JSON.stringify(req.body.name));
});
app.listen(3000, () => {
console.log('listening on 3000');
});
admin.ejs
<!DOCTYPE Html>
<html>
<head>
<title>Admin Login</title>
</head>
<body>
<div>
<center padding="100px">
<form method="post" action="/admin">
<div> Secret Key:
<input name='name'></input>
</div><br></br><br></br>
<div>
<button type="submit" onClick='smsAPI()'>Get OTP</button>
</div>
</form>
</center>
</div >
</body>
</html>
你得到输入。“”中的“name”是一个通过method='post'传递数据的变量。对于多个数据输入,name='name[]'。
因此,
on name='name'
input: Adu
backend: "Adu"
OR
input: Adu, Luv,
backend: "Adu, Luv,"
on
name='name[]'
input: Adu,45689, ugghb, Luv
backend: ["Adu,45689, ugghb, Luv"]
好吧,这可能听起来很蠢,但对我来说很管用。
作为一个完全的初学者,我没有意识到写作:
router.post("/", (res, req) => {
console.log(req.body);
req.send("User Route");
});
是错的!
你必须确保你以正确的顺序传递post/get的参数(req,res):并相应地调用它们:
router.post("/", (req, res) => {
console.log(req.body);
res.send("User Route");
});
问题得到了解答。但由于它是相当通用和要求。body未定义是一个常见的错误,特别是对于初学者,我发现这是恢复我所知道的关于这个问题的最好地方。
此错误可能由以下原因引起:
1. [服务器端][经常]忘记或误用解析器中间件
您需要使用适当的中间件来解析传入的请求。例如,express.json()以JSON格式解析请求,express.urlencoded()以urlencoded格式解析请求。
const app = express();
app.use(express.urlencoded())
app.use(express.json())
您可以在express文档页面中看到完整的列表
如果在Express中找不到适合请求的解析器(XML、form-data…),就需要为它找到另一个库。例如,要解析XML数据,可以使用这个库
您应该在路由声明部分之前使用解析器中间件(我做了一个测试来确认这一点!)中间件可以在初始化express app后立即配置。
像其他答案指出的那样,bodyParser自express 4.16.0以来就已弃用,您应该像上面那样使用内置中间件。
2. [客户端][很少]忘记随请求一起发送数据
你需要发送数据…
要验证数据是否已随请求一起发送,请打开浏览器的devtools中的Network选项卡并搜索您的请求。
这种情况很少见,但我看到一些人试图在GET请求中发送数据,因为GET请求请求。Body未定义。
3.[服务器和客户端][经常]使用不同的内容类型
Server and client need to use the same Content-Type to understand each other. If you send requests using json format, you need to use json() middleware. If you send a request using urlencoded format, you need to use urlencoded()...
There is 1 tricky case when you try to upload a file using the form-data format. For that, you can use multer, a middleware for handling multipart/form-data.
What if you don't control the client part? I had a problem when coding the API for Instant payment notification (IPN). The general rule is to try to get information on the client part: communicate with the frontend team, go to the payment documentation page... You might need to add appropriate middleware based on the Content-Type decided by the client part.
最后,给全栈开发者一个建议:)
当遇到这样的问题时,尝试使用一些API测试软件,如Postman。目标是消除客户端部分的所有噪声,这将帮助您正确识别问题。
在Postman中,一旦得到正确的结果,就可以使用软件中的代码生成工具来获得相应的代码。按钮</>在右边栏上。你有很多流行语言/库的选择…
历史:
早期版本的Express曾经捆绑了许多中间件。bodyParser是附带的中间件之一。当Express 4.0发布时,他们决定从Express中移除捆绑的中间件,并将它们作为单独的包。在安装bodyParser模块后,语法从app.use(express.json())改为app.use(bodyParser.json())。
bodyParser在4.16.0版本中被添加回Express,因为人们希望它像以前一样与Express捆绑在一起。这意味着如果您使用的是最新版本,则不必再使用bodyParser.json()。您可以使用express.json()代替。
对于那些感兴趣的人来说,4.16.0的发布历史在这里,拉请求在这里。
好吧,言归正传,
实现:
你需要加的就是加,
app.use(express.json());
app.use(express.urlencoded({ extended: true}));
app.use(app.router); // Route will be at the end of parser
并删除bodyParser(在新版本的express中不需要)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
快递公司会处理您的要求。:)
完整的例子是这样的,
const express = require('express')
const app = express()
app.use(express.json())
app.use(express.urlencoded({ extended: true}));
app.post('/test-url', (req, res) => {
console.log(req.body)
return res.send("went well")
})
app.listen(3000, () => {
console.log("running on port 3000")
})
在express 4及以上版本中,你不需要body解析器,它们有自己的json解析方法,
在您的express应用程序的高设置级别添加
var express = require('express');
var app = express()
app.use(express.json()); //declare this to receive json objects.
其他答案没有提到,当通过fetch或其他客户端进行表达请求时。请求必须以某种方式格式化。
const response = await fetch(`${expressAddress}/controller/route`, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
headers: {
'Content-Type': 'application/json' //this must be set to a json type
},
body: JSON.stringify(row) //regular js object need to be converted to json
})
如果你像这样进行取回请求。Body将按预期输出json对象。
当我遇到同样的问题时,尽管我知道BodyParser已不再使用
我已经使用了app.use(express.json())
问题是{对我来说}:
我在放置
app.use (express.json ())
后
App.use ('api/v1/example', example) =>{涉及路由}
一旦我重新排列这两行;
1 - app.use(express.json())
2 -应用程序(“火/v1/example”,example)
效果很好
首先,确保在路由之前应用这个中间件(express.urlencoded)。
let app = express();
//response as Json
app.use(express.json());
//Parse x-www-form-urlencoded request into req.body
app.use(express.urlencoded({ extended: true }));
app.post('/test',(req,res)=>{
res.json(req.body);
});
代码express.urlencoded({extended:true})只响应x-www-form-urlencoded post请求,所以在ajax/XMLHttpRequest/fetch中,确保您正在发送请求。setRequestHeader(“内容类型”、“应用程序/ x-www-form-urlencoded”);头。
就是这样!
更新2022
你可以用。
app.use (express.json ())
const express = require('express')
const app = express();
const PORT = process.env.PORT || 3001
// Calling the express.json() method for parsing
app.use(express.json())
app.listen(PORT, () => {
console.log(`============ API Gateway is open at ${PORT} ============= `)
})
Express. json()是Express中内置的中间件函数。此方法用于解析带有JSON有效负载的传入请求,并基于body解析器。
该方法返回只解析JSON并且只查看内容类型头与类型选项匹配的请求的中间件。
表达。json vs bodyParser.json