Express 4.17.1 req.body returns undefined - javascript

The code is split into 2 files:
the main file: server.js
the router file: user.js
In the user.js file req.body returns undefined and doesn't save the data to database
The data sent to /user/register returns 'Could not save to database'.
I've tried bodyParser.json() and bodyParser.urlencoded({extended: true}), although it isn't required in express 4.17.x, and they do not work.
Other common solutions like app.use(express.json()) also didn't help.
server.js
const express = require('express')
const mongoose = require('mongoose')
const User = require("./models/userSchema");
const userRouter = require('./routes/user')
const placeRouter = require('./routes/place');
const bodyParser = require('body-parser');
const app = express()
const PORT = 5000
app.use(express.json())
mongoose.connect('mongodb://localhost:27017/instaDB', {
useNewUrlParser: true,
useUnifiedTopology: true
}, () => {
console.log('Connected to Database');
})
app.use('/user', userRouter)
app.listen(PORT, ()=>{
console.log(`Listening on PORT: ${PORT}`);
})
user.js
const express = require('express')
const User = require("../models/userSchema");
userRouter = express.Router()
userRouter.post('/register', (req, res) => {
const {username, password} = req.body
console.log(req.body.username);
console.log(password);
User.findOne({username}, (err, user) => {
if(err){
res.status(500).json({
err: true,
msgBody: 'Server Error'
})
} if(user){
res.status(400).json({
err: true,
msgBody: 'Username already exists'
})
}
else{
const newUser = new User({
username,
password
})
newUser.save((err)=>{
if(err){
res.status(500).json({
err: true,
msgBody: 'Could not save to database'
})
} else {
res.status(200).json({
err: false,
msgBody: 'Registered Successfully'
})
}
})
}
})
})
module.exports = userRouter;

I would guess the initial request lacks the header Content-Type: application/json.
So Express json parser ignores the request body as it is not typed as json.
So the parser does not fill the req.body field.
Try adding this header with this value (Content-Type: application/json) to your request.
How you will do that depends on how you send this request (curl, postman, javascript xhr, react/angular..., lib...)

Related

NodeJs Rest api: I can make calls in postman but the route returns as not found in url

When I make a post request to the /login endpoint in postman it works fine and returns all the information. However when I try to navigate to the end point in the url the route returns unfound. In the console I get GET http://localhost:5000/login 404 (Not Found). Why is the console returning for a get request? If I try to call the post request in axios I get xhr.js:177 POST http://localhost:3000/login 404 (Not Found).
app.js
require("dotenv").config();
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const router = express.Router();
const cors = require('cors');
const app = express();
app.use(cors())
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
const mongoose = require('mongoose');
const connection = "password"
mongoose.connect(connection, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
})
const clientRoutes = require('./routes/clientRoutes');
const traderRoutes = require('./routes/traderRoutes');
const loginRoute = require('./routes/loginRoute')
app.use('/', clientRoutes, traderRoutes, loginRoute);
// setup a friendly greeting for the root route
app.get('/', (req, res) => {
res.json({
message: 'Welcome to the REST API for Pave!',
});
});
// send 404 if no other route matched
app.use((req, res) => {
res.status(404).json({
message: 'Route Not Found',
});
});
// setup a global error handler
app.use((err, req, res, next) => {
if (enableGlobalErrorLogging) {
console.error(`Global error handler: ${JSON.stringify(err.stack)}`);
}
res.status(err.status || 500).json({
message: err.message,
error: {},
});
});
app.listen(5000, () => console.log('Listening on port 5000!'))
loginRoute.js
require("dotenv").config();
const express = require("express");
const router = express.Router();
const jwt = require("jsonwebtoken");
const bcryptjs = require("bcryptjs");
const Client = require("../models/clientSchema");
const Trader = require("../models/traderSchema");
function asyncHandler(callback) {
return async (req, res, next) => {
try {
await callback(req, res, next);
} catch (error) {
next(error);
console.log(error);
}
};
}
router.post('/login', asyncHandler(async (req, res, next) => {
let user = req.body;
const trader = await Trader.findOne({ emailAddress: req.body.emailAddress })
if (user && trader) {
console.log(trader)
let traderAuthenticated = await bcryptjs.compareSync(user.password, trader.password);
console.log(traderAuthenticated)
if (traderAuthenticated) {
console.log('Trader match')
const accessToken = jwt.sign(trader.toJSON(), process.env.ACCESS_TOKEN_SECRET)
res.location('/trader');
res.json({
trader: trader,
accessToken: accessToken
}).end();
} else {
res.status(403).send({ error: 'Login failed: Please try again'}).end();
}
} else if (user && !trader) {
const client = await Client.findOne({emailAddress: req.body.emailAddress})
console.log(client)
let clientAuthenticated = await bcryptjs.compareSync(user.password, client.password);
console.log(clientAuthenticated)
if (clientAuthenticated) {
console.log('Client match')
const accessToken = jwt.sign(client.toJSON(), process.env.ACCESS_TOKEN_SECRET)
res.location('/client');
res.json({
client: client,
accessToken: accessToken
});
} else {
res.status(403).send({ error: 'Login failed: Please try again'}).end();
}
} else {
res.status(403).send({ error: 'Login failed: Please try again'}).end();
}
})
);
module.exports = router;
You set POSTMAN to make a POST request, right? When you enter a url in the browser, that causes a GET request - and you have no route to manage this that I can see, but for the default Not found.
you are calling with axios with wrong port no. it should, POST method http://localhost:5000/login as your application is running on port 5000.
but you are calling, POST http://localhost:3000/login

MongoDB Returns Empty Error Object when Making POST Request

I'm currently learning about APIs. I'm using Dev Ed's video on a RESTful MERN API. I set up my routes and I could successfully connect to my MongoDB database. However, when attempting to call save() on a post to the DB, I was returned my error message, a JSON object with a message containing the err, but my err object was completely empty.
posts.js:
const express = require('express');
const router = express.Router();
const Post = require('../models/Post');
router.get('/', (req, res) => {
res.send('We are on /posts!');
});
router.post('/', (req, res) => {
const post = new Post({
title: req.body.title,
desc: req.body.desc,
});
post.save()
.then(data => {
res.json(data);
})
.catch(err => {
res.json({ message: err });
});
});
module.exports = router;
app.js:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
require('dotenv/config');
const app = express();
const PORT = 8080;
app.use(bodyParser.json());
// Import Routes ------------------------
const postsRoute = require('./routes/posts');
app.use('/posts', postsRoute);
// ROUTES --------------------------------
app.get('/', (req, res) => {
res.send('We are home!');
});
mongoose.connect(
process.env.DB_CONN,
{ useNewUrlParser: true },
() => {
console.log('Succesfully connected to DB!')
});
app.listen(PORT);
Post.js (schema):
const mongoose = require('mongoose');
const PostSchema = mongoose.Schema({
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now,
}
});
module.exports = mongoose.model('Posts', PostSchema);
My POST request and response (Postman):
In my code, I am attempting to send the new Post to my DB, but instead I get an error, an empty one. I either need to figure out how to view my error correctly (so that's it's not empty) or the larger problem: why my POST request is failing.
Again, I am learning about APIs, this is my very first time writing one. If there's anything I missed (like other code that you would need) or if there's something I should be doing differently, please, let me know! Thank you in advance!
use status when you want to use res like this:
for success result
res.status(200).json(data);
for .catch
res.status(500).json({ message: err });
but I prefer use async/await with try/cacth like this:
router.post('/', async(req, res) => {
const post = new Post({
title: req.body.title,
desc: req.body.desc,
});
try {
let data = await post.save()
res.status(200).json(data)
} catch (error) {
res.status(500).json({ message: error});
}
});
check the documentation of promises in mongnoos
check the connection of mongoose like this:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
require('dotenv/config');
const app = express();
const PORT = 8080;
app.use(bodyParser.json());
// Import Routes ------------------------
const postsRoute = require('./routes/posts');
app.use('/posts', postsRoute);
// ROUTES --------------------------------
app.get('/', (req, res) => {
res.send('We are home!');
});
runMongoose()
app.listen(PORT);
async function runMongoose(){
try {
await mongoose.connect(
process.env.DB_CONN,
{ useNewUrlParser: true }
);
console.log("mongodb is OK");
} catch (error) {
console.log("mongodb Warning", error);
}
}
if Succesfully connected to DB! printed mongoose connection is OK
the problem is that you added
{ useNewUrlParser: true }
remove that and it's gonna work fine ;)

Why the user = await User.findOne({ email }) returns null?

I'm setting up a login route and I decided to test it with postman and it worked but later when I was checking my DB configuration I found an error when I fixed the error the login test on postman doesn't work
so in my server.js file I have :
const express = require("express");
const connectDB = require("./config/db");
const app = express();
// Connect to MongoDB
connectDB();
// Initialize middleware
app.use(express.json());
// Define routes
app.use("/api/users", require("./routes/users"));
app.use("/api/auth", require("./routes/auth"));
app.use("/api/posts", require("./routes/posts"));
app.use("/api/profile", require('./routes/profile'));
// Create server
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
The connectDB function in config/db.js :
const mongoose = require("mongoose");
require('dotenv').config()
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true
});
console.log("Successfully connected to MongoDB");
} catch (err) {
console.error(err.message);
}
};
module.exports = connectDB;
In the auth.js route :
const express = require("express");
const router = express.Router();
const { check } = require("express-validator");
const {auth} = require('../middlewares/auth');
const {login} = require('../controllers/authController');
// #route: POST api/auth
// #desc: Login
// #access: Public
router.post("/",
[
check("email", "Email is required").not().isEmpty(),
check("password", "Password is required").not().isEmpty(),
],
login
);
module.exports = router;
The Auth controller in controllers/authController.js :
const { validationResult } = require("express-validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
require('dotenv').config()
exports.login = async (req, res) => {
try {
// Check for validation errors
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Check if user exists
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ msg: "Invalid credentials : you must register" });
}
// If exists, check password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ msg: "Invalid credentials : wrong password" });
}
// Return jwt
const payload = {
user: {
id: user.id,
},
};
jwt.sign(payload,
process.env.JWT_SECRET,{expiresIn: 3600},(err, token) => {
if (err) throw err;
res.json({ token });
}
);
} catch (err) {
console.error(err.message);
res.status(500).send("There was an error with the server. Try again later.");
}
}
Everything looks great and when I try to login with postman it returns the "Invalid credentials : you must register" message from this code in authController.js ( when I console.log(user) it returns null ) :
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ msg: "Invalid credentials : you must register" });
}
PS: At first, in the db configuration I forgot to add the mongo client options and everything worked and it returns the token in postman but after fixing the error I had the login problem

404 error when trying to post to api route

I am trying to implement authentication into my react app and I am recieving a 404 error whenever I try to POST to one of my express API routes while deployed. The server that I am deploying throus is AWS EC2 if it makes a difference.
Here is my Server.js file:
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const passport = require('passport');
const cors = require('cors');
const users = require('./routes/api/users');
const app = express();
app.use(cors());
// Bodyparser Middleware
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
// DB Config
const db = require('./config/keys').mongoURI;
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true, useUnifiedTopology: true }
)
.then(() => console.log("MongoDB successfully connected"))
.catch(err => console.log(err));
// Passport middleware
app.use(passport.initialize());
// Passport config
require('./config/passport')(passport);
// Routes
app.use('/api/users', users)
// Serve static assets if in production
if (process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`));
My ./routes/api/users.js file:
const express = require("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const keys = require("../../config/keys");
// Load input validation
const validateRegisterInput = require("../../validation/register");
const validateLoginInput = require("../../validation/login");
// Load User model
const User = require("../../models/User");
// #route POST api/users/register
// #desc Register user
// #access Public
router.post("/register", (req, res) => {
// Form validation
const { errors, isValid } = validateRegisterInput(req.body);
// Check validation
if (!isValid) {
return res.status(400).json(errors);
}
User.findOne({ email: req.body.email }).then(user => {
if (user) {
return res.status(400).json({ email: "Email already exists" });
} else {
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password
});
// Hash password before saving in database
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => res.json(user))
.catch(err => console.log(err));
});
});
}
});
});
// #route POST api/users/login
// #desc Login user and return JWT token
// #access Public
router.post("/login", (req, res) => {
// Form validation
const { errors, isValid } = validateLoginInput(req.body);
// Check validation
if (!isValid) {
return res.status(400).json(errors);
}
const email = req.body.email;
const password = req.body.password;
// Find user by email
User.findOne({ email }).then(user => {
// Check if user exists
if (!user) {
return res.status(404).json({ emailnotfound: "Email not found" });
}
// Check password
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
// User matched
// Create JWT Payload
const payload = {
id: user.id,
name: user.name
};
// Sign token
jwt.sign(
payload,
keys.secretOrKey,
{
expiresIn: 31556926 // 1 year in seconds
},
(err, token) => {
res.json({
success: true,
token: "Bearer " + token
});
}
);
} else {
return res
.status(400)
.json({ passwordincorrect: "Password incorrect" });
}
});
});
});
module.exports = router;
Here is an example of one of my calls made to the express api:
// Register User
export const registerUser = (userData, history) => dispatch => {
axios
.post("http://localhost:5000/api/users/register", userData)
.then(res => history.push("/login")) // re-direct to login on successful register
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
When I submit my form when I deploy to my server I get this error:
POST https://domainname.net/api/users/register 404 (Not Found)
I am running my front end on port 3000 and my api server on port 5000. All of my code works locally, and I have no idea what's happening when I deploy to my ec2 server.
Try this:
export const registerUser = (userData, history) => dispatch => {
axios
.post("http://yourdomain:5000/api/users/register", userData)//change in url
.then(res => history.push("/login")) // re-direct to login on successful
register
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
After your domain,you need to give port number of your server.Because by default POST https://domainname.net/api/users/register 404 (Not Found) will take port number as 80.So nothing will be there.
in your react app package.json file add below line :
"proxy": "http://localhost:5000", // server port
and your url for action will be :
axios.post("/api/users/register", userData)
so when you run production build for react app , it will in client/build folder and you statically serve that folder . client and server will be on same port 5000
so /api/users/register will be sent to server running port 5000

req.body is empty in express

I am creating a nodejs api in window using express framework. I alerady used body-parser.json(). But req.body is coming empty in linux.The program is properly working in windows but in linux, req.body is empty and req.body.name key is undefined.
I already tried the following steps : -
app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json())
const express = require('express'),
app = express(),
config = require('./config/configFile'),
route = require('./routes/userRoute'),
bodyParser = require('body-parser'),
mongoose = require('mongoose')
app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json()) // with this you can send the data to api in json format
app.get('/',(req,res)=>{
res.send({
"message":"API started"
})
})
app.use('/api/',route)
mongoose.Promise = global.Promise
mongoose.connect(config.dbPath,{useNewUrlParser: true})
.then(()=>{
console.log("Db is connected")
}).catch(err=>{
console.log(err)
})
app.listen(config.serverPort,()=>{
console.log('server started')
})
const userModel = require('../models/userModel')
module.exports = {
"registerUser": (req,res)=>{
if(!req.body){
res.status(400).send({
"message": "User Detail Cannot be empty"
})
} else{
const user = new userModel({
name : req.body.name,
email : req.body.email,
password : req.body.password
})
user.save().then(data=>{
res.status(200).send(data)
}).catch(err=>{
res.status(500).send({
"message": err.message || "Something went wrong"
})
})
}
},
"login":(req,res)=>{
res.send({
"message":"This is an register method"
})
}
}
In your routes file, you can handle the POST request like,
var express = require('express');
var router = express.Router();
router.post('/', function(req, res, next) {
// req.body will contain the body data.
res.send('respond with a resource');
});
module.exports = router;
You need to register your route with express router.
Your userRoute.js must look something like this.
var express = require('express');
var router = express.Router();
router.post("/registerUser", (req,res)=>{
if(!req.body){
res.status(400).send({
"message": "User Detail Cannot be empty"
})
} else{
const user = new userModel({
name : req.body.name,
email : req.body.email,
password : req.body.password
})
user.save().then(data=>{
res.status(200).send(data)
}).catch(err=>{
res.status(500).send({
"message": err.message || "Something went wrong"
})
})
res.send(req.body)
}
});
router.post("/login", (req,res)=>{
res.send({
"message":"This is an register method"
})
});
module.exports = router;

Categories

Resources