使用Express.js无法从请求中获取POST请求体

34

我正在使用NodeJS和Express(以及更多类似于mongo、sockets等的东西)开发一个API,但我认为我卡在了一个非常简单的步骤上。 我只是尝试从POST req对象中获取信息,但在尝试访问req.body时出现错误。

下面是我的代码:

var express     = require('express'),
    http        = require('http'),
    path        = require('path'),
    fs          = require('fs'),
    io          = require('socket.io');
    dynroute    = require('dynroute');

var app = express();
app.set('port', process.env.PORT || 3999);
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(app.router);
app.use(express.bodyParser());

app.post('/user', function(req, res) {

    console.log(JSON.stringify(req.body));
    res.send(req.body.self);
});

http.createServer(app).listen(app.get('port'), function ()
{
    console.log('App Server is now running at:' + app.get('port'));     
});

console.log(JSON.stringify(req.body));中,我得到了undefined,而在res.send(req.body.self);中,我得到了TypeError: Cannot read property 'self' of undefined

我一直在寻找这种类型的错误,通常问题是人们没有包含app.use(express.bodyParser());中间件,所以我也尝试使用app.use(express.urlencoded());app.use(express.json());,但都不起作用。

如果我执行console.log(req),我可以看到整个对象,但当我从客户端进行POST请求时(我将其作为JSON传递),我无法看到body或任何我传递的内容。

**我知道我可以使用restifysails.js在Node中构建API,但我想自己做所有事情,以便我可以从经验中学习。*

谢谢

编辑: 我必须在app.router中间件之前放置bodyparser中间件,这解决了问题!


我建议您发布有关如何进行帖子请求的信息。如果'req'对象没有捕获'body',那么我的第一个想法是post请求未成功。 - Michael
我正在使用一款名为Advanced Rest Client的Chrome应用程序,只需通过POST请求将['user':'kevinblanco']作为内容传递到我的URL,并使用application/json作为内容类型标头。 - kevinblanco
我希望Express、Node或其他内容中有一个单一的版本号,可以在这个问题(及其答案)中指示。我认为现在它已经过时了,因为今天当远程服务器返回4xx状态码时,我遇到了这样的问题。Express 4.13.1。BodyParser 1.13.2。但是已接受的答案无法解决问题。 - Marco Faustinelli
10个回答

41

bodyParser 中间件移到 router 中间件上方!

var app = express();
app.set('port', process.env.PORT || 3999);
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(app.router);

很高兴能帮助你@kevinblanco - 如果这解决了你的问题,请接受答案:)) - Renato Gama
6
如果你今天想要避免令人烦恼(但是暂时性的)弃用警告,当你使用bodyParser时,可以改为使用以下方式:app.use(express.urlencoded()); app.use(express.json()); 这两种方法的效果相同。 - jsplaine
非常感谢renatoargh...在看到您的回答之前,我简直要疯了。 - Pradyumna Swain
别忘了在请求头中使用 Content-Type: application/json 来调用您的服务器,否则在 req.body 中将没有任何数据。 - Christiaan Westerbeek
我在今天下班前两分钟找到了这个解决方案。谢谢! - Jobsamuel
找到 express.bodyParser() 真是太难了! - bmustata

18

Content-Type = "application/json" 应该是 请求头 中的一项。


1
我不知道为什么你被踩了。Express 4.0版本已经包含了你评论中列出的所有修复,所以它们是无用的。在使用REST测试扩展时,必须分配Content-Type。太棒了 :) - Alex Boisselle
2
这在我的情况下也是成立的,因为在 Google Chrome 中使用本机的 fetch API 不会将 content-type 标头默认设置为 application/json,因此服务器端永远不会进行任何正文解析,因为传入的请求必须被解释为文本。 - A-Dubb

5

BodyParser不再与Express捆绑

npm install body-parser
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: false }));

3
为了解析 JSON 数据,添加以下代码:app.use(bodyParser.json()) - Camilo Silva
截至2016年1月,该bug仍然存在。我正在使用Express 4.13.1和BodyParser 1.13.2。只有当状态码为4xx时,我无法获取body:错误页面的渲染失败,节点服务器崩溃。当状态码为2xx时,没有问题。尝试了此页面提出的所有解决方案。这很奇怪! - Marco Faustinelli
我正在使用express 4.16.4版本。 这对我不起作用。app.use(bodyParser.urlencoded({extended: true}))app.use(bodyParser.json())app.post('/user_create',(req,res)=>{console.log("尝试创建用户"); const firstName = req.body.create_first_name const lastName = req.body.create_last_name console.log("名字是 "+firstName+" "+lastName); res.end()}) - Vivek Pratap Singh

1

在我的情况下,我需要添加这两行代码来读取POST请求体

app.use(express.json());

// add this middleware to read post request body
app.use(express.text());

1
对我来说,@kevinblanco的注释“我必须在app.router中间件之前添加bodyparser中间件,这样就可以解决问题!”对我有用。将其放在单独的答案中,因为它被埋在底部。
你的代码应该像这样:
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// My routing here

1

以上列出的大部分答案都是正确的,但目前[2020年7月28日]最合适的答案是使用内置的express,即:

app.use(express.json());

这将作为中间件来接受您请求中的JSON对象。

0
你必须安装bodyParser,然后像这样在你的应用中使用它:
// middlewares
app.use(bodyParser.json());
app.use(sucursalRoutes);
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

希望这对你有所帮助。

0

Express有一个内置的方法,可以从客户端发来的POST请求中识别JSON对象。您可以在index.js文件中使用此方法,而无需使用body-parser:

app.use(express.json());


0
在Golang中,您可以在向Nodejs Express路由器发起POST HTTP客户端请求之前将Content-Type设置为application/json:
//Golang
import (    
    "bytes"
    "encoding/json"
    "errors"    
    "net/http"      
)

//method := "POST"
//url := "http://ip:port/api/router"

func request(method string, url string, data interface{}, pHeader map[string]string) {
    pBody, err := json.Marshal(data)
    if err != nil {
        return []byte{}, err
    }
    request, err = http.NewRequest(method, url, bytes.NewBuffer(pBody))
    if(err!=nil ){
        return []byte{}, err
    }
    request.Header.Set("Content-Type", "application/json")

    //add header params if any
    for key, head := range pHeader {
        request.Header.Add(key, head)
    }

    client := &http.Client{}
    resp, err := client.Do(request)
    if err != nil {
       return []byte{}, err
    }
    defer resp.Body.Close() 
}

//NODEJS

//app.js
var express = require('express');
...

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


var router= require('path/to/router.js');
//use the router
app.use('/api', router);
...

//router.js    
router.post('/router', function (req, res, next) {
    //log request body to view its values of incoming request
    console.log('req.body', req.body)
})

0

您不需要使用bodyParser。只需添加以下几行代码即可 -

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接