'Why is req.body undefined in Express?
I am creating a PUT method to update a given set of data however in my update function, req.body is undefined.
controller.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, '*');
How it should look:
"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"
}
The first function where I check if a review exists work with my delete method. Am I missing something in one of these functions that would make req.body undefined?
Solution 1:[1]
Nobody in the other answers is really explaining the "why" here. By default req.body
is undefined
or empty and the Express engine does not read the body of the incoming request.
So, if you want to know what's in the body of the request and, even further, if you want it read and then parsed into req.body
so you can directly access it there, then you need to install the appropriate middleware that will see what type of request it is and if that's the type of request that has a body (like a POST or a PUT) and then it will look at the incoming content-type and see if it's a content-type that it knows how to parse, then that middleware will read the body of the request, parse it and put the parsed results into req.body
so it's there when your request handler gets called. If you don't have this type of middleware installed, then req.body
will be undefined
or empty.
Express has middleware like this built in for several content-types. You can read about them here in the Express doc. There is middleware for the following content types:
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"
So, you will need some middleware to parse your specific content so you can access it in req.body
. You don't say exactly data type you're using, but from your data expectations, I would guess that perhaps it's JSON. For that, you would place this:
app.use(express.json());
Somewhere before your PUT request handler. If your data format is something else, then you could use one of the other built-in middleware options.
Note, for other data types, such as file uploads and such, there are whole modules such as multer
for reading and parsing those data types into properties that your request handler can offer.
Solution 2:[2]
You should use a body parser. Basically, Express can't know how to parse the incoming data the users throw at it, so you need to parse the data for it. Luckily, there are a few body parsers (and for quite some time body parsers for JSON and UrlEncoded (not sure if there are any others) are built into Express itself). The way you do that is you add a middleware in your express app like that:
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
Solution 3:[3]
Make sure that you have body-parser
middleware installed, which extract the body of request stream and exposes it on req.body
(source)
npm install body-parser --save
Here's how express server definitions would look like:
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())
Solution 4:[4]
To get access to request body, you need to use express.json(). Make sure before using router, just wire your app.use(express.json()) that should make the request object available.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | jfriend00 |
Solution 2 | |
Solution 3 | mehowthe |
Solution 4 | Sidd Thota |