Express.js req.body undefined

时间:2012-02-07 13:25:08

标签: node.js express

我将此作为Express服务器的配置

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());造成的,但是你可以看到我在路线之前调用它。

有任何线索吗?

39 个答案:

答案 0 :(得分:244)

您必须确保在定义路线之前定义所有配置。如果您这样做,则可以继续使用express.bodyParser()

一个例子如下:

var express = require('express'),
    app     = express(),
    port    = parseInt(process.env.PORT, 10) || 8080;

app.configure(function(){
  app.use(express.bodyParser());
  app.use(app.router);
});

app.listen(port);

app.post("/someRoute", function(req, res) {
  console.log(req.body);
  res.send({ status: 'SUCCESS' });
});

答案 1 :(得分:208)

最新版本的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())

答案 2 :(得分:59)

没有。您需要在app.use(express.bodyParser())之前使用app.use(app.router)。事实上,app.use(app.router)应该是你打电话的最后一件事。

答案 3 :(得分:36)

首先确保你已经安装了名为' body-parser'的npm模块。致电:

npm install body-parser --save

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

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

app.use(bodyParser.json());

答案 4 :(得分:33)

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

确保您使用的是application / x-www-form-urlencoded,application / json或其他内容,这取决于您的帖子数据。将此字段留空将使Express感到困惑。

答案 5 :(得分:32)

正如在一条评论中发布的那样,我使用

解决了这个问题
app.use(require('connect').bodyParser());

而不是

app.use(express.bodyParser());

我仍然不知道为什么简单的express.bodyParser()无效...

答案 6 :(得分:20)

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

答案 7 :(得分:16)

Express 4,具有内置的主体解析器。无需安装单独的正文解析器。因此,下面将起作用:

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

答案 8 :(得分:10)

看起来身体解析器不再附带快递。我们可能需要单独安装它。

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

答案 9 :(得分:9)

express.bodyParser()需要被告知它正在解析的内容类型。因此,您需要确保在执行POST请求时,您要包含“Content-Type”标头。否则,bodyParser可能不知道如何处理POST请求的正文。

如果您使用curl执行包含正文中的某个JSON对象的POST请求,它将如下所示:

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

如果使用其他方法,只需确保使用适当的约定设置该标题字段。

答案 10 :(得分:9)

万一有人遇到我遇到的同样问题;我正在使用

这样的网址前缀
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); 

答案 11 :(得分:8)

您可以尝试在顶部添加以下代码行(在您的require语句之后):

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

关于其起作用的原因,请查看文档:{​​{3}}

答案 12 :(得分:5)

今天发生在我身上。以上解决方案均不适合我。但是一点点谷歌搜索帮我解决了这个问题。我正在为微信第三方服务器编码。

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

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

答案 13 :(得分:5)

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

答案 14 :(得分:4)

app.use(express.json());

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

的问题

答案 15 :(得分:4)

浪费了很多时间:

取决于客户请求中的内容类型 服务器应该有不同的,下面是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'}));

然后,req.body工作正常。

答案 16 :(得分:4)

在我的情况下,这是因为在包含路由之后使用了body-parser。

正确的代码应该是

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

答案 17 :(得分:4)

要使用,您需要在 app.use(express.bodyParser())之后 app.use(app.router),就像那样:

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

答案 18 :(得分:4)

var bodyParser = require('body-parser');
app.use(bodyParser.json());

这节省了我的一天。

答案 19 :(得分:3)

问题得到解答。但由于它非常通用,而且 req.body undefined 是一个经常出现的错误,特别是对于初学者来说,我发现这是恢复我对问题的所有了解的最佳位置。

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

1. [SERVER 端] 忘记或误用解析器中间件

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

您可以在 express documentation page

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

  • 就像其他答案指出的那样,bodyParser 自 express 4.16.0 起已被弃用,您应该使用上述内置中间件。

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

  • 好吧,您需要发送数据...

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

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

3. [SERVER & CLIENT] 使用不同的 Content-Type

  • 服务器和客户端需要使用相同的 Content-Type 才能相互理解。如果您使用 json 格式发送请求,则需要使用 json() 中间件。如果您使用 urlencoded 格式发送请求,则需要使用 urlencoded()...

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

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

最后,给全栈开发人员的一条建议:)

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

在 Postman 中,一旦得到正确的结果,就可以使用软件中的代码生成工具来生成对应的代码。按钮 </> 位于右侧栏上。你有很多流行语言/库的选择...... enter image description here

答案 20 :(得分:2)

此问题可能是因为您没有使用正文解析器(link

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

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

答案 21 :(得分:2)

我的是文本输入,无论如何,我都会在此处添加此答案,以便对人们有所帮助。解析时请确保设置了编码!在为它设置适当的值之前,我一直在努力使其发挥作用。

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

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());并不能解决我的问题。

未定义现在更改为对象。根据Express documentation,如果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)

您设置的编码类型也必须是on point。就我而言,它是文本/纯文本。您可以更改它以满足您的需求,例如JSON等。我做到了,瞧!像魅力一样工作!

app.use(express.text({
    type: "text/plain" 
}));

答案 22 :(得分:2)

您可以使用快速身体解析器。

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

答案 23 :(得分:1)

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

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

答案 24 :(得分:1)

在@ kevin-xue的基础上建议,需要声明内容类型。在我的实例中,这只发生在IE9上,因为XDomainRequest doesn't set a content-type,所以bodyparser和expressjs忽略了请求的主体。

我通过在将请求传递给body解析器之前显式设置content-type来解决这个问题,如下所示:

keytool -keystore mark.jks -alias markkey -genkey -keyalg RSA
Enter keystore password: password
Re-enter new password: password

答案 25 :(得分:1)

感谢 @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)
{

});

注意: 对于大型有效负载 - 请使用数组缓冲区(more @ MDN

答案 26 :(得分:1)

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

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

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

答案 27 :(得分:1)

在Express 4中,这非常简单

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

app.use(express.json()) 

答案 28 :(得分:1)

大多数时间req.body由于缺少JSON解析器而未定义

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

答案 29 :(得分:1)

如果您使用某些外部工具来发出请求,请确保添加标题:

Content-Type: application/json

答案 30 :(得分:1)

我用以下方法解决了它:

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

答案 31 :(得分:0)

当您忘记输入元素中的name属性时,获取空request.body的另一种可能方法...

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

答案 32 :(得分:0)

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

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

答案 33 :(得分:0)

对于以上答案均不起作用的任何人,我都必须在前端和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());
    

到您的快速app.js页。 (在npm install cors之后)

答案 34 :(得分:0)

最新版本的Express已经内置了body-parser。因此,您可以使用:

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

答案 35 :(得分:0)

添加您的app.js
呼叫路由器之前

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

答案 36 :(得分:0)

一个简单的例子来说明所有问题:

登录后Method ='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"]

答案 37 :(得分:0)

总是将中间件用作第一位。

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

在路线之前。

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

答案 38 :(得分:-4)

好吧,这听起来很愚蠢,但对我有用。

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

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