Node JS req.body undefined

5

我看了很多其他帖子,但对此非常困惑。

我可以运行console.log(req)并获得以下输出

ServerResponse {
  ...
  req: 
   IncomingMessage {
    ...
     url: '/my-endpoint',
     method: 'POST',
     statusCode: null,
     statusMessage: null,
     ...
     body: { foo: 'bar' },
     _body: true,
     ...
     route: Route { path: '/my-endpoint', stack: [Object], methods: [Object] } },
  ...

看起来很稳定,所以我期望执行console.log(req.body)并在控制台中收到{ foo: 'bar' },但是没有,收到的是undefined

经过研究,我发现可能与我的app.js文件有关,特别是与body-parser有关,然而,我已经设置好了所有这些内容

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var http = require('http');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

//Home Page Rendering
var index = require('./routes/index');
app.use('/', index);

// All other routes are kept in the `routes` module
require('./routes')(app);

module.exports = app;

routes.js

module.exports = function routing(app) {
  var apiClient = require('./services/apiClient');

  app.post('/get-device-info', function(err, req, res){
    console.log("/get-device-info routes");
    apiClient(req, res);
  });
};

apiClient.js

module.exports = function callApi(req, res){
  console.log(req);
  console.log(req.body)
};

index.js

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

以下是我尝试过的方法:

app.use(express.bodyParser());

确保传入请求明确声明为application/json格式

以其他方式声明body parser.json

添加配置函数


你正在使用哪个版本的Express?建议你使用4.x版本,并且单独使用 body-parser 模块,而不是express.bodyParser。你也能包括索引路由函数吗? - E net4
他确实坚持使用独立的body-parser... - Jakub Pastuszuk
我不确定为什么我的回答被踩了。我在原始帖子中添加了更多的代码。我正在使用Node 7.4.0和Express 4.15.0。 - Lucas Crostarosa
请在浏览器的网络选项卡中包含发送到服务器的请求头,以便服务器在处理它们之前可以查看。 - Kevin B
2个回答

5
你的问题在于Express没有使用错误优先回调作为其路由处理程序。下面的代码将无法工作,因为app.post处理程序没有签名(req, res) => {}。在下面的代码中,err等于reqreq等于resres等于next
// routes.js
module.exports = function routing(app) {
  var apiClient = require('./services/apiClient');

  app.post('/get-device-info', function(err, req, res){
    console.log("/get-device-info routes");

    // Assuming the request is correct 
    // the value of body will be the request body  
    console.log(res.body)

    apiClient(req, res);
  });
};`

在Express中,有三种不同的路由回调函数签名可供使用

  • (req, res) => {} - 这是最基本的签名,定义了一个只关心请求和响应的路由。
  • (req, res, next) => {} - 这是中间件回调函数签名,看起来像一个基本的路由回调函数,但它还分配了next对象,告诉Express调用下一个匹配的路由。
  • (err, req, res, next) => {} - 这是错误处理路由回调函数,每个Express路由器中间件或Express应用程序只需要一个。如果在路由或中间件中调用了next(err),则会调用它。更具体地说,如果next()没有以字符串或空值的形式调用,则它将跳过所有剩余的中间件和路由,并直接进入错误处理程序。您可以在Express文档中阅读更多信息。

您需要更改路由定义为

app.post('/get-device-info', (req, res) => {
  apiClient(req, res)
})

或者你甚至可以这样做

module.exports = app => {
  let apiClient = require('./services/apiClient')

  app.post('/get-device-info', apiClient)
}

我知道这是一些愚蠢的事情......我没想到回调签名顺序很重要。谢谢。 - Lucas Crostarosa

1

我曾经试过这个方法,你可以尝试一下。

首先要声明app,然后再声明bodyParser,因为bodyParser是在app中使用的:

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

然后有以下这些行:
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))

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