Express.js点播。身体未定义

我有这个作为我的快速服务器的配置

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 is undefined。下面是一个使用req.body的路由示例:

app.post('/admin', function(req, res){
console.log(req.body.name);
});

我读到这个问题是由缺少app.use(express.bodyParser());引起的,但正如你所看到的,我在路由之前调用它。

有线索吗?

594861 次浏览

不。你需要在app.use(app.router)之前使用app.use(express.bodyParser())。事实上,app.use(app.router)应该是你调用的最后一个东西。

正如已经发布在一个评论下,我解决了它使用

app.use(require('connect').bodyParser());

而不是

app.use(express.bodyParser());

我仍然不知道为什么简单的express.bodyParser()不工作…

UPDATE July 2020

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
})

更多信息见在这里

> .

original follows

.

在定义路由之前必须确定所有的配置。如果你这样做,你可以继续使用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.bodyParser()需要被告知它正在解析的内容类型。因此,您需要确保在执行POST请求时,包含了“Content-Type”标头。否则,bodyParser可能不知道如何处理POST请求的主体。

如果你使用curl来执行一个POST请求,其中包含一些JSON对象,它看起来会像这样:

curl -X POST -H "Content-Type: application/json" -d @your_json_file http://localhost:xxxx/someRoute

如果使用其他方法,请确保使用合适的约定设置报头字段。

请求头中的Content-Type非常重要,特别是当你从curl或任何其他工具中发布数据时。

确保你使用的是application/x-www-form-urlencoded, application/json之类的,这取决于你的post数据。将此字段保留为空将使Express混淆。

为了工作,你需要在app.use (express.bodyParser ())之后加上app.use (app.router),就像这样:

app.use(express.bodyParser())
.use(express.methodOverride())
.use(app.router);

看来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

最新版本的Express (4.x)将中间件从核心框架中分离出来。如果需要正文解析器,则需要单独安装它

npm install body-parser --save

然后在代码中这样做

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())

如果你发布SOAP消息,你需要使用原始体解析器:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');


app.use(bodyParser.raw({ type: 'text/xml' }));

这是我今天想到的。以上方法对我都没用。但稍微搜索一下帮助我解决了这个问题。我正在为微信第三方服务器编码。

当node.js应用程序需要读取流POST数据(例如来自REST客户端的请求)时,情况会稍微复杂一些。在这种情况下,请求的属性“readable”将被设置为true,并且POST数据必须以块的形式读取,以便收集所有内容。

http://www.primaryobjects.com/CMS/Article144

根据@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());
var bodyParser = require('body-parser');
app.use(bodyParser.json());

这帮了我大忙。

首先,确保你已经安装了名为'body-parser'的npm模块,调用:

npm install body-parser --save

然后确保在调用路由之前包含了以下行

var express = require('express');
var bodyParser = require('body-parser');
var app = express();


app.use(bodyParser.json());
// Require body-parser (to receive post data from clients)


var bodyParser = require('body-parser');


app.use(bodyParser.urlencoded({ extended: false }))


// parse application/json


app.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

例子:

< p >对我来说, 在客户端,我有下面的标题:

Content-Type: "text/xml"

因此,在服务器端,我使用:

app.use(bodyParser.text({type: 'text/xml'}));

然后,要求。身体工作正常。

您可以使用表达体解析器。

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));

以防有人遇到和我一样的问题;我使用一个url前缀像

http://example.com/api/

哪一个是用路由器设置的

app.use('/api', router);

然后我有了以下内容

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

什么修复了我的问题是将身体解析器配置放在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);

Express 4,有内置的正文解析器。不需要安装单独的体解析器。所以下面的内容是可行的:

export const app = express();
app.use(express.json());

你可以试着在顶部添加这行代码(在require语句之后):

app.use(bodyParser.urlencoded({extended: true}));

至于为什么它工作的原因,请查看docs: https://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions

在路由前使用app.use (bodyparser.json ());。/ /。 app.use(“/ api”,航线);< / p >

如果你使用一些外部工具来发出请求,请确保添加头文件:

Content-Type: application/json

我用:

app.post('/', bodyParser.json(), (req, res) => {//we have req.body JSON
});

这也是一种可能性:确保你应该在app.js(或index.js)文件的路由之前写这个代码。

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

添加你的app.js

在路由器调用之前

const app = express();
app.use(express.json());

此问题可能是因为您没有使用body-parser (链接)

var express = require('express');
var bodyParser  = require('body-parser');


var app = express();
app.use(bodyParser.json());

最新版本的Express已经内置了体解析器。所以你可以用:

const express = require('express);
...
app.use(express.urlencoded({ extended: false }))
.use(express.json());

对于那些上面没有一个答案的人来说,我必须在我的前端和express之间启用cors。

你可以这样做:

  1. 下载并打开浏览器的CORS扩展,例如:

    https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en

    对于Chrome浏览器,

或通过

  1. 添加行

    var cors=require('cors');
    
    
    app.use(cors());
    

to your express app.js page. (After npm install cors)

另一种获取空请求的方法。正文,当您忘记输入元素的name属性时…

<input type="text" /> /* give back empty request.body -> {}*/
<input type="text" name="username" /> /* give back request.body -> {"username": "your-input"} */

大部分时间需要。由于缺少JSON解析器,body未定义

const express = require('express');
app.use(express.json());

可能缺少体解析器

const bodyParser  = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));

有时由于cros原点没有定义,所以加起来

const cors = require('cors');
app.use(cors())

在路由中添加express.urlencoded({ extended: true })可以解决这个问题。

router.post('/save',express.urlencoded({ extended: true }),  "your route");

在特快4中,这非常简单

const app = express()
const p = process.env.PORT || 8082


app.use(express.json())

我的是一个文本输入,我在这里添加了这个答案,所以它会帮助人们。确保在解析时设置了编码!我努力让它工作,直到我给它设置了一个合适的值。

这是我在没有使用任何解析器的情况下得到的错误:

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-parser,但是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"
}));

在我的例子中,这是因为在包含路由之后使用了body-parser。

正确的代码应该是

app.use(bodyParser.urlencoded({extended:true}));
app.use(methodOverride("_method"));
app.use(indexRoutes);
app.use(userRoutes);
app.use(adminRoutes);
app.use(express.json());

这将有助于解决req.body未定义的问题

简单的例子,通过所有:

方法='post'登录后的快捷代码:

这将不需要任何这样的bodyParser()。

enter image description here

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>

你得到输入。“名字”中的“;”;是一个通过method='post'传递数据的变量。对于多个数据输入,name='name[]'。

因此,

on name='name'


input: Adu
backend: "Adu"


OR


input: Adu, Luv,
backend: "Adu, Luv,"

name='name[]'
input: Adu,45689, ugghb, Luv
backend: ["Adu,45689, ugghb, Luv"]

中间件总是首先使用。

//MIDDLEWARE
app.use(bodyParser.json());
app.use(cors());
app.use(cookieParser());

在路线之前。

//MY ROUTES
app.use("/api", authRoutes);

好吧,这可能听起来很蠢,但对我来说很管用。

作为一个完全的初学者,我没有意识到写作:

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");
});

当我使用bodyParser时,它被标记为已弃用。为了避免这种情况,我使用下面的代码和express代替bodyParser。

注意:路由必须声明最后,这是重要的!这里的其他回答很好地描述了这个问题。

const express = require("express");
const app = express();


const routes = require('./routes/api');


app.use(express.json());
app.use(express.urlencoded({ extended: false }));


// Routes must declared finally
app.use('/', routes);

问题得到了解答。但由于它是相当通用的,而且req.body undefined是一个常见的错误,特别是对初学者来说,我发现这是恢复我所知道的关于这个问题的最好地方。


此错误可能由以下原因引起:

1. [服务器端][经常]忘记或误用解析器中间件

  • 您需要使用适当的中间件来解析传入的请求。例如,express.json()解析JSON格式的请求,而express.urlencoded()解析urlencoded格式的请求。
const app = express();
app.use(express.urlencoded())
app.use(express.json())

你可以在快速文档页中看到完整的列表

  • 如果你在Express (XML, form-data…)中找不到适合你的请求的解析器,你需要为它找到另一个库。例如,要解析XML数据,可以使用这个库

  • 你应该使用解析器中间件之前的路由声明部分(我做了一个测试来确认这一点!)中间件可以在初始化express app后立即配置。

  • 像其他答案指出的那样,bodyParser自express 4.16.0以来已弃用,你应该像上面那样使用内置中间件。

2. [客户端][很少]忘记随请求一起发送数据

  • 你需要发送数据…

要验证数据是否与请求一起发送,请在浏览器的devtools中打开网络选项卡并搜索您的请求。

  • 这种情况很少见,但我看到一些人试图在得到请求中发送数据,因为GET请求req.body是未定义的。

3.(服务器,[经常]使用不同的内容类型

  • 服务器和客户端需要使用相同的内容类型来相互理解。如果你使用json格式发送请求,你需要使用json()中间件。如果你使用urlencoded格式发送请求,你需要使用urlencoded()

  • 当你尝试使用form-data格式上传文件时,有一个棘手的情况。为此,你可以使用< >强乘< / >强,一个用于处理多部分/表单数据的中间件。

  • 如果你不控制客户端部分怎么办?我在为即时付款通知(IPN)编写API时遇到了一个问题。一般的规则是尝试获取客户端部分的信息:与前端团队沟通,进入支付文档页面……您可能需要根据客户端部分决定的Content-Type添加适当的中间件。

最后,给全栈开发者一个建议:)

当遇到这样的问题时,尝试使用一些API测试软件,如Postman。目标是消除客户端部分的所有噪声,这将帮助您正确识别问题。

在Postman中,一旦你得到了正确的结果,你就可以使用软件中的代码生成工具来获得相应的代码。按钮</>在右边栏上。你有很多流行语言/库的选择… enter image description here < / p >
You have to check following things for that:-
1. app.use(bodyParser.urlencoded({ extended: false }))


// parse application/json
app.use(bodyParser.json())
Implement body parser in your app.


2. Check headers in postman its should be based on your rest api's, like if your Content-Type: application/json it should be defined in your postman headers.

历史:

早期版本的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应用程序的highset级别添加

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对象。

使用这一行在任何get或post请求之前在顶部进行适当的解析:

app.use(express.json())

它将json数据解析为Javascript对象。

在我的例子中,我所做的是在我的路由之前声明app.use(express.json()); app.use(express.urlencoded({ extended: false }));,问题得到了解决。我希望这对你也有帮助!

当我遇到同样的问题时,尽管我知道BodyParser不再被使用 并且我已经使用了app.use(express.json()) 问题是{对我来说}: 我放置

app.use(express.json())

app.use('api/v1/example', example) =比;{涉及路线}

一旦我重新排列这两行;

1 - __abc0

2 - __abc0

效果很好

首先,确保在路由之前应用这个中间件(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 的帖子请求,所以在你的ajax / XMLHttpRequest /取回中,确保你发送的是request.setRequestHeader('Content-type', 'application/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载荷< / >强的传入请求,并基于< >强bodyparser < / >强

该方法返回只解析JSON并且只查看内容类型头与类型选项匹配的请求的中间件。

express.json vs bodyParser.json .json

更新日期:2022年10月

首先使用以下步骤检查或添加主体解析器:

< p >步骤:1

. import bodyParser from 'body-parser' < p >步骤2: app.use (bodyParser。Urlencoded ({extended: false})); app.use (bodyParser.json ()); < / p >

步骤3:最重要的路由器应该在body解析器下面定义,这是body未定义....的主要原因

import noteRouter from "./src/routes/category_routes.js";

app.use (noteRouter);

无论你的名字定义在路由器取决于你..

希望这对你们有帮助

试试这个

npm i multer --save
const express = require('express');
const multer  = require('multer');
const upload = multer();
const app = express();


app.post('/test', upload.any(), (req, res) => {
console.log('data', req.body);
res.send(req.body);
});