Undefined values in req.body - node.js

When I wanna make a POST req using Postman where I already set the content-type to application/json and I console.log the req.body.name or sth else it only returns undefined.
Here's the code:
index.js
const app = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const authRoute = require("./routes/auth");
dotenv.config();
mongoose.connect(
process.env.DB_CONNECT,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => console.log("connected to mongoDB")
);
// Middleware
app.use(express.json());
// Routes
app.use("/api/user", authRoute);
// Run Server
const PORT = 5000;
app.listen(PORT, () => console.log(`server running on port ${PORT}`));
auth.js
const router = require("express").Router();
const User = require("../model/User");
router.post("/register", async (req, res) => {
const user = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password,
});
console.log(req.body.name);
});
module.exports = router;

Since you are not using body parser and using only express.json() send requests as raw then pick JSON. The format that you should write looks like this:
{
"name": "Some name",
"lastname": "...."
}
Here is how your postman should look like:

Install Body parser as:
npm install --save body-parser
and then update your index.js file as:
var bodyParser = require('body-parser')
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));

just add these line after
// Middleware
app.use(express.json());
for example
// Middleware
app.use(express.json());
app.use(express.urlencoded{extended: true})
This express setting will allow you to parse html-body

Related

HTTP requests receive 404 in browser but work fine in Postman

I've deployed my app to Heroku and it builds fine and my React app is rendering pages correctly. However, when I try to submit a POST request to sign up a user or log a user in, I get a 404 error. I do not, however, have this problem when submitting requests from Postman. My front end is using React and Axios for submitting requests. Server is using Nodejs and Express. I was thinking it had something to do with CORS, but I've tried configuring CORS and it hasn't resolved the issue.
Front-end code for POST request:
axios.defaults.withCredentials = true;
signUp: function(userInfo) {
userInfo = {
email: userInfo.email,
password: userInfo.password,
firstName: userInfo.firstName,
lastName: userInfo.lastName,
mobileNumber: userInfo.mobileNumber
}
return axios.post('/users/signup', userInfo);
Server file
const express = require('express');
const session = require('express-session');
const passport = require('./config/passport');
const path = require("path");
const cors = require('cors');
const cookieParser = require("cookie-parser");
const app = express();
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const db = require('./models');
const sessStore = new SequelizeStore({
db: db.sequelize
});
const http = require('http').Server(app);
const routes = require('./routes');
const PORT = process.env.PORT || 3000;
const corsConfig = {
origin: "https://example.herokuapp.com/",
credentials: true
}
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
app.use(cors(corsConfig));
}
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(session({
secret: process.env.SESSION_SECRET,
name: process.env.SESSION_NAME,
store: sessStore,
resave: false,
saveUninitialized: false }));
app.use(cookieParser());
app.use(passport.initialize());
app.use(passport.session());
app.use(routes);
app.get("*", function(req, res) {
res.sendFile(path.join(__dirname, "./client/build/index.html"));
});
db.sequelize.sync().then(() => {
http.listen(PORT, () => console.log(`Listening at http://localhost:${PORT}`));
});
Routes index file
const router = require("express").Router();
const usersRoutes = require('./users');
const isAuthenticated = require('../../config/middleware/isAuthenticated');
router.use("/users", usersRoutes);
Users Routes file
const router = require("express").Router();
const passport = require('../../config/passport');
const usersController = require("../../controllers/usersController");
router
.route('/signup')
.post(usersController.createNewUser);
router
.route('/login')
.post(passport.authenticate('local'), usersController.logUserIn);
Controller
createNewUser: function(req, res) {
db.User.create({
email: req.body.email,
password: req.body.password,
firstName: req.body.firstName,
lastName: req.body.lastName,
mobileNumber: req.body.mobileNumber
})
.then(() => res.sendStatus(200))
.catch((err) => res.send(err));
}
I resolved this. The url in the axios call was missing a piece. The reason this worked locally is because I had the proxy in React set to include the missing piece so axios calls done locally were always being sent to the right url, but they were not being sent to the right url in prod. Really relieved it was something so simple!

Postman keeps loading on sending POST request to an express route

I created a route and controller for my sign up.
Here's my route:
const express = require("express");
const router = express.Router();
const { signup } = require("../../controllers/auth");
router.post("/signup", signup);
module.exports = router;
And here's my controller:
exports.signup = () => (req, res) => {
const { name, email, password } = req.body;
res.json({
user: { name, email, password },
});
};
Inside my server.js file I register both:
const express = require("express");
const morgan = require("morgan");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const mongoose = require("mongoose");
require("dotenv").config();
// routes
const blogRoutes = require("./routes/blog");
const authRoutes = require("./routes/auth");
// app
const app = express();
// db
mongoose
.connect(process.env.DATABASE, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log("DB connected!"));
// middlewares
app.use(morgan("dev"));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser());
// cors
if (process.env.NODE_ENV == "development") {
app.use(cors({ origin: `${process.env.CLIENT_URL}` }));
}
// routes middleware
app.use("/api", blogRoutes);
app.use("/api", authRoutes);
// port
const port = process.env.PORT || 8000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Now on my POSTMAN, I tried to put the data using POST http://localhost:8000/api/signup with the header and raw setup right.
{
"name": "SyRyan",
"email": "syryan#gmail.com",
"password": "brace1010"
}
The database is connected but the postman takes forever to load the json request back. Am I making any mistakes here? Please help!
I think that the problem is that signup is a function that returns a function, but it should be just a function that receives req & res as parameters:
exports.signup = (req, res) => {
const { name, email, password } = req.body;
res.json({
user: { name, email, password },
});
};

Empy req.body in NodeJs, Express

I'm trying to send a json to my nodeJs app through POST Method in body.
For that I'm using POSTMAN to create the request, with the proper consnt-type header and body JSON Rows. Tho the message back is "OK" in console the req.body is {} empty.
Would you have an idea what's wrong in my code?
const bodyParser = require('body-parser');
const { Client } = require('pg');
const express = require('express');
const app = express();
// create application/json parser
const jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
const urlencodedParser = bodyParser.urlencoded({ extended: false })
const hostname = '127.0.0.1';
const port = 3000;
const dbSchema = 'public';
const client = new Client({
user: 'postgres',
host: 'localhost',
database: 'postgres',
password: '123123',
port: 5432,
});
client.connect();
/* =========== Some Initialize staff =============== */
// parse various different custom JSON types as JSON
app.use(bodyParser.json({ type: 'application/*+json' }))
app.use(bodyParser.urlencoded({
extended: true
}));
app.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
/* =========== FROM HERE =============== */
app.post('/post-test', urlencodedParser, (req, res) => {
console.log('Got body:', req.body);
res.sendStatus(200);
});
app.get('/',(req,res)=>{
res.status(200).send('Get Ready for something awesome!\n');
});
enter image description here
You should use app.use(bodyParser.json());, in your code const jsonParser = bodyParser.json() this is not used.
Update: Or you can apply jsonParser middleware directly to the post route:
app.post("/post-test", jsonParser, (req, res) => {
console.log("Got body:", req.body);
res.json({ ...req.body });
});
Can't figure what is happening so, I am posting the code that works for me -
let express = require('express');
let app = express();
const authorRoute = express.Router();
authorRoute.use(express.json());
authorRoute.use(express.urlencoded({extended:true}));
authorRoute.post('/post-test', async (req, res) => {//req.body});
app.use(authorRoute);
Also, make sure to test with a well-formed JSON.
version "express": "^4.17.1",

Unable to post json data using postman in nodejs server

What am I doing wrong here? I saw somewhere that body-parser is now inbuilt in express in express, I tried that also still the same result.
app.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
require("dotenv/config");
const posts = require("./routes/posts");
const bodyParser = require("body-parser");
//middleware to use "/posts" whenever we go to posts
app.use("/posts", posts);
app.use(bodyParser.json()); //parsing json
//routes
app.get("/", (req, res) => {
//handle root
res.send("We are home");
});
//how do we start listening/connect to the server
mongoose.connect(
process.env.DB_CONNECTION,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => console.log("connected to DB!")
);
app.listen(3000);
Post.js
const mongoose = require("mongoose");
const PostSchema = mongoose.Schema({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now(),
},
});
module.exports = mongoose.model("Posts", PostSchema);
posts.js
const express = require("express");
let router = express.Router();
const Post = require("../models/Post");
//middleware
/*router.use(function(req, res, next){
console.log(req.url, "#", Date.now());
next();
})*/
router
.route("/")
.get((req, res, next) => {
res.send("hi get /posts");
})
.post((req, res, next) => {
console.log(req.body);
});
module.exports = router;
Terminal always shows that its undefined.
here's a screenshot of postman:
Yes bodyParser is included in the current versions of expressjs, and you can apply it like this:
app.use(express.json());
Also this middleware must be applied before using routes. So the order must be like this:
app.use(express.json()); //parsing json
app.use("/posts", posts);

Request body undefined in supertest

I am testing an express API with supertest. I am trying to pass in body parameters into the test, as can be seen in the code snippets below, but it appears that the body parameters don't get passed in correctly since I get an error message that the body parameters are undefined.
Running the test with command mocha --recursive returns the following error:
Cannot read property 'email' of undefined
Below is the code from file email-suite.js referencing supertest
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var mongoose = require("mongoose");
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var supertest = require("supertest");
var chai = require("chai");
var should = chai.should();
var api = require("../server.js");
describe("Email Module", function() {
this.timeout(25000);
before(function(done){
mongoose.createConnection(/* connectionstring */);
mongoose.connection.on('open', function(err) {
if(err) console.log(err);
console.log('connected to server');
});
done();
});
it("Check Email Count", function(done) {
var body = { email: "email#email.com" };
supertest(api)
.post("/emailCount")
.set('Accept', 'application/json')
.send(body) // body is undefined
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if(err) return done(err);
res.body.count.should.equal(2);
done();
});
});
});
Below is the code from file email-api.js
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var router = express.Router();
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
router.post('/emailCount', function(req, res) {
var email = req.body.email; // req.body is undefined
}
module.exports = router;
Below is the code from the file server.js
var express = require("express");
var app = express();
app.set("port", process.env.PORT || 3000);
var router = require("./user/email-api");
app.use('/', router);
app.listen(app.get("port"), function() {
console.log("App started on port " + app.get("port"));
});
module.exports = app;
Put body-parser always after express object and before every routes in main server file like this
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
//Router task start from here
Other wise always will get undefined since router call first and body parsed later.
Thank you abdulbarik for your answer. I want to add some extra information to aid clarity in case people are still getting undefined values for the request body object, and if (as in my case) your routers and tests are setup differently.
Here is the router that we shall test:
// router.js
const express = require("express");
const router = express.Router();
router.post("/", (req, res) => {
res.json({ success: true, data: req.body });
});
module.exports = router;
The following test code will result in the request body being undefined, and thus the test failing:
// router.test.js
const express = require("express");
const request = require("supertest");
const bodyParser = require("body-parser");
// set up the test app - this will fail
const app = express();
app.use("/routerPath", require("./router")); // this will cause the test to fail, as the router should be setup after the body-paser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// run the test
it("successful response", async () => {
const response = await request(app)
.post("/routerPath")
.send({
firstname: "John",
lastname: "Smith",
})
.set("Accept", "application/json");
expect(response.status).toEqual(200);
expect(response.body).toEqual({
success: true,
data: {
firstname: "John",
lastname: "Smith",
},
});
});
The reason why, as explained by abdulbarik, is that the body-parser code should always be before the router code, so that the parser runs before the router. To make the test pass, simply swap these lines around:
// set up the test app - this will work now
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/routerPath", require("./router")); // the router setup should happen after the body-parse setup
I hope that is a helpful clarification.

Resources