【问题标题】:Express.js + body-parser: empty req.body from POST requestExpress.js + body-parser:来自 POST 请求的空 req.body
【发布时间】:2018-01-28 18:49:48
【问题描述】:

我正在使用Expressbody-parser 中间件来处理传入的请求。在前端,我有一个表单,它只是一个隐藏的输入和一个提交按钮(用 Pug 编写):

form(notes="saveNotesForm" action=`/lessons/${lesson._id}/notes` method="POST" enctype="application/x-www-form-urlencoded")
              input(type="hidden" id="hiddenNotes" name="hiddenNotes" alt="Notes Copy" value="test").notesHidden
              input(type="submit" name="saveNotes" alt="Save Notes" value="Save")

在后端,我有使用 body-parser 的 Express 应用程序:

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

以及处理传入请求的路由:

router.post('/lessons/:lessonID/notes', lessonController.updateNotes);

// ... and in lessonController:

exports.updateNotes = async (req, res) => {
  console.log('updateNotes request received');
  console.log(req.body);
  res.status(200).json({ status: 'success' });
}

当我尝试在updateNotes 中使用req.body 时,主体是一个空对象,但至少应该具有属性hiddenNotes,其值为"test"。如果您有任何问题或认为您发现了问题,请发表评论!

[更新]

这是一个愚蠢的错误,我忘记了我已经为提交此表单时编写了一个单独的事件处理程序 - 在我完成所有代码之前我只是在 SO 上发布了 :) 事件处理程序使用 axios 和看起来像这样:

const SaveNotesButton = $('form.saveNotes');
SaveNotesButton.on('submit', ajaxSaveNotes);

function ajaxSaveNotes(e) {
  e.preventDefault();
  axios
    .post(this.action)
    .then(res => {
      console.log(res.data);
    })
    .catch(console.error);
}

很遗憾,在用axios制作posts时,需要像这样将数据包含在对象中,否则请求中不会包含:

const SaveNotesButton = $('form.saveNotes');
SaveNotesButton.on('submit', ajaxSaveNotes);

function ajaxSaveNotes(e) {
  e.preventDefault();
  axios
    .post(this.action, { notes: this.children.hiddenNotes.value }) // Data added here
    .then(res => {
      console.log(res.data);
    })
    .catch(console.error);
}

【问题讨论】:

  • 您是否尝试过将bodyParser.urlencoded 更改为在bodyParser.json 之前调用。不确定它是否有任何区别,但我编写了自己的中间件来捕获原始正文请求,所以我不会丢失任何东西,我发现在bodyPaser.json 之后,req.on('end') 事件已经触发,阻止我记录数据.在此之前放置我的中间件(以及其他一些更改)使我能够解决问题。

标签: javascript node.js express body-parser


【解决方案1】:

不确定您是如何定义路线的,但我希望发布路线如下所示:

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

app.post('/lessons/:lessonID/notes', (req, res) => {
    // now pass the req object to your function
    lessonController.updateNotes(req);
});

您需要将 req 对象传递给您的函数才能访问 req.body...

【讨论】:

  • express 应用的路由只是被分解成一个单独的文件(而不是与app.post 在同一行),lessonController.updateNotes 函数接收 req 和 res 对象。
  • I made a very obvious mistake,与我在这篇文章中包含的代码无关。看看我对 OP 的更新!
  • 很高兴您对它进行了排序!
【解决方案2】:

您的req.body 未定义的原因可能有一种解释。你确定你的app.use(bodyParser.json())app.use(bodyParser.url... 写在你的app.use('***', router) 行之前吗?如果将主体解析器中间件放在路由器中间件之后,它基本上不会被调用,因为中间件是按照它们在app.use 中的顺序调用的。因此,您应该将 bodyParser 放在所有路由器逻辑之前。 BodyParser 中间件然后调用它之后的所有其他中间件(填充了req.body),包括您的所有路由器级中间件。

希望对您有所帮助!

【讨论】:

  • 你好,Mustansir!是的,我是app.use-ing bodyParser,在应用程序包含路线之前几行。
  • 您是否尝试过将内容类型更改为 application/json?
  • 我没有尝试更改 enctype - but I made a very obvious mistake,与我在这篇文章中包含的代码无关。一秒看一眼我对 OP 的更新!
  • 哦。在那种情况下太好了!
【解决方案3】:

是否必须尝试使用​​ Postman 或类似工具查询您的端点?

【讨论】:

  • 是的,我尝试在 Postman 中重新创建请求,但正文仍然没有显示任何数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-25
  • 2018-10-16
  • 1970-01-01
  • 2021-10-10
  • 1970-01-01
  • 1970-01-01
  • 2016-10-14
相关资源
最近更新 更多