为什么在Express中req.body未定义?

4
我正在创建一个PUT方法以更新给定的一组数据,但在我的更新函数中,req.body未定义。
控制器.js
async function reviewExists(req, res, next) {
  const message = { error: `Review cannot be found.` };
  const { reviewId } = req.params;
  if (!reviewId) return next(message);
  let review = await ReviewsService.getReviewById(reviewId);
  if (!review) {
    return res.status(404).json(message);
  }
  res.locals.review = review;
  next();
}

async function update(req, res, next) {
  console.log(req.body);
  const knexInstance = req.app.get('db');
  const {
    review: { review_id: reviewId, ...review },
  } = res.locals;

  const updatedReview = { ...review, ...req.body.data };

  const newReview = await ReviewsService.updateReview(
    reviewId,
    updatedReview,
    knexInstance
  );
  res.json({ data: newReview });
}

service.js

const getReviewById = (reviewId) =>
  knex('reviews').select('*').where({ review_id: reviewId }).first();

const updateReview = (reviewId, updatedReview) =>
  knex('reviews')
    .select('*')
    .where({ review_id: reviewId })
    .update(updatedReview, '*');

应该是什么样子:

"data": {
    "review_id": 1,
    "content": "New content...",
    "score": 3,
    "created_at": "2021-02-23T20:48:13.315Z",
    "updated_at": "2021-02-23T20:48:13.315Z",
    "critic_id": 1,
    "movie_id": 1,
    "critic": {
      "critic_id": 1,
      "preferred_name": "Chana",
      "surname": "Gibson",
      "organization_name": "Film Frenzy",
      "created_at": "2021-02-23T20:48:13.308Z",
      "updated_at": "2021-02-23T20:48:13.308Z"
    }

我检查评论是否存在的第一个函数与我的删除方法一起使用。我是否在这些函数中漏掉了什么会导致req.body未定义?

4个回答

18
没有其他答案中真正解释“为什么”。默认情况下,req.bodyundefined或为空,并且Express引擎不会读取传入请求的主体。因此,如果您想知道请求主体中的内容,并进一步将其读取并解析为req.body,以便可以直接在那里访问它,则需要安装适当的中间件,该中间件将查看请求类型是否具有主体(例如POST或PUT),然后它将查看传入的content-type并查看它是否是它知道如何解析的content-type,然后该中间件将读取请求的主体、对其进行解析并将解析结果放入req.body中,因此当调用请求处理程序时,它就在那里。如果您没有安装此类型的中间件,则req.body将是undefined或为空。Express内置了几个此类内容类型的中间件。您可以在这里阅读有关它们的文档。这是以下内容类型的中间件:
express.json(...)    for "application/json"
express.raw(...)     reads the body into a Buffer for you to parse yourself
express.text(...)    for "text/plain" - reads the body into a string
express.urlencoded(...) for "application/x-www-form-urlencoded"

所以,您需要一些中间件来解析您的特定内容,以便您可以在req.body中访问它。您没有明确说明您使用的数据类型,但根据您的数据期望,我猜测可能是JSON。为此,您应该放置以下内容:

app.use(express.json());

在您的PUT请求处理程序之前某个位置。如果您的数据格式是其他格式,则可以使用其他内置中间件选项之一。

请注意,对于其他数据类型(例如文件上传等),有整个模块,例如multer用于将这些数据类型读取和解析为您的请求处理程序可以提供的属性。


@alexwhitmore - 这个回答解决了你的问题吗? - jfriend00

7
你应该使用一个body parser。基本上,Express 不知道如何解析用户在其上投掷的传入数据,所以你需要为它解析数据。幸运的是,有一些body parsers(JSON和UrlEncoded的body parsers 已经内置到 Express 中)。你可以通过在 Express 应用程序中添加中间件来实现:
const app = express();

...

app.use(express.json({
    type: "*/*" // optional, only if you want to be sure that everything is parsed as JSON. Wouldn't recommend
}));

...
// the rest of the express app

2

请确保已安装 body-parser 中间件,该中间件可以提取请求流的主体并将其公开在 req.body 上 (source)

npm install body-parser --save

以下是Express服务器定义的样例:
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())


请注意,如果 XMLHttpRequest 使用 FormData,则传入的请求表单数据需要进行多部分解析(npmjs.com 上的 multer 可以实现此功能)。 - user5066707

0
要访问请求正文,您需要使用express.json()。在使用路由器之前,请确保只需将app.use(express.json())连接即可使请求对象可用。

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