EDIT: #LawrenceCherone solved this, its (req, res, next) not (err, res, req)
I am creating a MERN app (Mongo, express, react, node).
I have some routes that work fine and return data from mongodb. However I created a new controller to access a separate collection and whenever i try to create a new document in it my req.body returns undefined.
I have setup my server.js like this:
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const connectDB = require("./db");
const app = express();
const apiPort = 3000;
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors());
app.use(bodyParser.json());
connectDB();
app.use("/api", require("./routes/router"));
var server = app.listen(apiPort, () => console.log(`Server running on port ${apiPort}`));
module.exports = server;
My router looks like this:
const express = require("express");
const QuizController = require("../controllers/quiz-controller");
const UserController = require("../controllers/user-controller");
const router = express.Router();
// quiz routes
router.post("/quizzes", QuizController.createQuestion);
router.get("/quizzes", QuizController.getAllQuestions);
router.get("/quizzes/:quiz_name", QuizController.getQuestionsByQuiz);
router.get("/quizzes/questions/:question_id", QuizController.getQuestionById);
router.put("/quizzes/:question_id/edit", QuizController.updateQuestionById);
router.delete("/quizzes/:question_id", QuizController.deleteQuestionById);
// user routes
router.post("/users", UserController.createUser);
module.exports = router;
All of the /quizzes routes work perfectly fine and i have had no trouble accessing the body. The UserController.createUser method is almost identical to Quizcontroller.createQuestion too so I am very confused.
Here is the user-controller with the createUser function:
const User = require("../models/User");
createUser = async (err, res, req) => {
const body = req.body;
console.log(req.body);
console.log(req.params);
console.log(body);
if (!body) {
return res.status(400).json({
succes: false,
error: "You must provide a body",
});
}
try {
const newUser = new User(body);
console.log(newUser);
if (!newUser) {
return res.status(400).json({ success: false, error: err });
}
const user = await newUser.save();
return res
.status(200)
.json({ success: true, newUser: user, msg: "New user created" });
} catch (err) {
console.error(err.message);
res.status(500).send("Server error");
}
};
module.exports = { createUser };
Here is an image of the postman request I am using to try test this:
[1]: https://i.stack.imgur.com/UHAK5.png
And the user model:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true,
},
emailAddress: {
type: String,
required: true,
},
permission: {
type: String,
required: true,
},
auth0Id: {
type: String,
required: true,
},
});
module.exports = mongoose.model("users", UserSchema);
The functional parameter order matters.
its
createUser = async (req, res, next) => // correct format
Not
createUser = async (err, res, req) // wrong format
Related
I'm trying to POST Data to Mongo DB Using Express Js.
I'm new to express just learned for a backend server
This is my app.js
const express = require("express");
const mongoose = require("mongoose");
require("dotenv/config")
const User = require("./model/user.js")
let app = express();
app.use(express.json())
app.get("/", (req,res) => {
res.send("On Home!")
});
app.post("/register", async (req,res) => {
try {
const myUser = new User(req.body);
await myUser.save();
res.send(myUser);
} catch (err){
res.send({error : err});
}
});
mongoose.connect(process.env.DB_URI,(req,res) => {
console.log("Connected to Database!")
});
app.listen("5000" , () =>{
console.log("Listening on localhost 5000")
})
My user.js
const mongoose = require("mongoose");
const User = mongoose.Schema({
name: {
type: String,
required: true,
},
email:{
type:String,
required: true,
},
pass:{
type: String,
required: true,
}
});
module.exports = mongoose.model("user",User)
My Response Is
My Response
(I'm Using Postman to test)
Thank You For Your Support
You need to use body-parser, add this to your code:
var bodyParser = require('body-parser');
app.use(bodyParser.json());
I have some simple javascript code in three files. There is my server.js, which has
const userRouter = require('./routes/users')
app.use("/",userRouter)
Then there is my middleware users.js with
module.exports = router
and lastly user.js with
module.exports = {
User:User,
validateLogin:validateUserLogin,
validateRegister:validateUserRegister,
}
When my user.js had just the export line module.exports = User my code worked just fine. server.js imports users.js, which imports user.js. But when exporting functions along with my User object, my requests stop working. Why? How can I fix this? I'm using Node.js with express and mongo db. All my HTML requests are in users.js.
The code to my server.js is
const express = require('express');
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
//just show server is running
const app = express()
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
const PORT = 4000;
app.get("/status", async (req, res) => {
return res.status(400).send("server for GET is running");
});
app.post("/status", async (req, res) => {
return res.status(200).send({
status: "server for POST is running",
message: req.body.message
});
});
app.listen(PORT, function() {
console.log(`server running on port ${PORT}`);
});
const url = "mongodb+srv://Admin:strongpassword#cluster0.tjual.mongodb.net/ConfusedTom?retryWrites=true&w=majority"
mongoose.connect(url, {
useNewUrlParser: true,
useUnifiedTopology: true,
dbName: "ConfusedTom"
}).then(() => {
console.log("connected successfully to server, using database %s\n", mongoose.connection.$dbName);
}).catch(err => {
console.log(err);
});
const userRouter = require('./routes/users')
app.use("/",userRouter)
and here is my users.js
const mongoose = require("mongoose");
const express = require("express");
const router = express.Router();
const ObjectId = mongoose.Types.ObjectId;
const Review = require("../models/review.js")
const TVShow = require("../models/tvshows.js")
const { User, validateLogin, validateRegister} = require("../models/user.js")
router.get("/username", async (req, res) => {
console.log("reached!")
var user = await User.findOne({ username: req.body.username });
if (!user) return res.status(400).send("User doesn't exist.");
return res.status(200).send(user)
});
router.post("/register", async(req,res) => {
const { error } = validateRegister(req.body);
if (error) return res.status(400).send(error.details[0].message);
else user = await User.findOne({ username: req.body.username });
if (user) return res.status(400).send("Username already taken.");
//create new user
user = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
username: req.body.username,
password: req.body.password,
});
user.save();
return res.status(200).send("User registered successfully.");
})
router.post("/login", async (req, res) => {
console.log("reached!")
// validate the request body first
const { error } = validateLogin(req.body);
if (error) return res.status(400).send(error.details[0].message);
//find an existing user
var user = await User.findOne({ username: req.body.username });
if (!user) return res.status(400).send("Username reqired.");
if (user) {
if (user.validatePassword(req.body.password)) {
return res.header.status(200).send("User login successfully");
}
else return res.status(400).send("Password is incorrect");
} else return res.status(400).send("User doesn't exist.");
});
module.exports = router
The problem with your updated import of the stuff from user.js is you're using the wrong names for the functions. You currently have:
const UserStuff = require("../models/user.js")
const User = UserStuff.User;
const validateLogin = UserStuff.validateUserLogin;
const validateregister = UserStuff.validateUserRegister;
but the object you're exporting is:
module.exports = {
User:User,
validateLogin:validateUserLogin,
validateRegister:validateUserRegister,
}
You're using the wrong names of the functions (validateUserLogin instead of validateLogin). The names you use have to match at both ends. So:
const UserStuff = require("../models/user.js")
const User = UserStuff.User;
const validateLogin = UserStuff.validateLogin;
// ^^^^^^^^^^^^^
const validateregister = UserStuff.validateRegister;
// ^^^^^^^^^^^^^^^^
or more concisely:
const { User, validateLogin, validateRegister} = require("../models/user.js")
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 ;)
this is my app.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const mongoose = require("mongoose");
const inputRoutes = require("./routes/input");
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use(cors());
app.use((req, res, next) => {
res.setHeader("Acess-Control-Allow-Origin", "*");
res.setHeader(
"Acess-Control-Allow-Methods",
"OPTIONS ,GET ,POST ,PUT,PATCH , DELETE"
);
res.setHeader("Acess-Control-Allow-Headers", "Content-Type, Authorization");
next();
});
app.use("/input", inputRoutes);
mongoose
.connect("mongodb://localhost:27017/MEAN", { useNewUrlParser: true })
.then(result => {
app.listen(2400);
})
.catch(err => console.log(err));
this is my routes/input.js
const express = require("express");
const router = express.Router();
const inputController = require("../controller/input");
router.post("/todo", inputController.createTodos);
module.exports = router;
this is my controller,input.js
const Todo = require("../models/todos");
const { validationResult } = require("express-validator/check");
exports.createTodos = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const error = new Error("validation failed due to incorrect data");
error.statusCode = 442;
throw error;
}
const task = req.body.task;
const status = req.body.status;
console.log(task);
console.log(status);
const todo = new Todo({
task: task,
status: status
});
todo
.save()
.then(result => {
console.log(task);
res.status(201).json({
message: "post created sucessfully",
post: result
});
})
.catch(err => {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
});
};
this is my model.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const todoSchema = new Schema(
{
task: {
type: String,
required: true
},
status: {
type: Boolean,
default: false
}
},
{ timestamps: true }
);
module.exports = mongoose.model("Todo", todoSchema);
You need to send JSON request in the postman first choosing raw option, and then json in the right dropdown.
Also you seem to use express-validator package, but you don't use it in router.
In the router you can use it like this:
const express = require("express");
const router = express.Router();
const { check } = require("express-validator");
const inputController = require("../controller/input");
router.post("/todo", [
check("task")
.not()
.isEmpty()
], inputController.createTodos);
module.exports = router;
Also in controller you should import the validationResult from express-validator,
and validate the result like this:
const { validationResult } = require('express-validator');
exports.createTodos = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
....
}
I have a code, it should create mongoose.schema, save it, find it and check if its the same as the input. So i know i have an error but it wont log it in the console so i don't know whats the problem.
This is express node.js server, using mongoose and js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const model = require('.//models/schema');
app.use(express.static('public'));
app.get('/register', function(request, response) {
response.sendFile(__dirname + '/html/register.html');
});
app.get('/login', function(request, response){
response.sendFile(__dirname + '/html/login.html')
});
const listener = app.listen(3000, function() {
let myURL = new URL(`localhost:${listener.address().port}/register`);
console.log(myURL.href);
});
mongoose.connect(`mongodb://localhost${listener.address().port}:/register`, {
useNewUrlParser: true,
useUnifiedTopology: true
});
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.post('/submit-data', (req, res) => {
res.redirect('/login')
let user = new model({
all:{
'login': req.body.login,
'password': req.body.password,
'gender': req.body.gender,
'birthday': req.body.birthday
}});
user.save()
console.log('Successfuly Updated the data')
});
app.post('/submit-login', (req, res) => {
model.find({
'all.login': req.body.login,
'all.password': req.body.password}, function (err, user){
if(err){
console.log(err)
}
if(!user){
console.log('No such user')
}
console.log('Successfully logged in')
});
});
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let schema = new Schema({
all:{
'login': String,
'password': String,
'gender': String,
'birthday': String
}});
module.exports = mongoose.model('allInfo', schema);
I expected it to log error if its incorrect or to log "Successfully logged in" but it wont log any error.
You can do it like this
const existingUser = await model.findOne({all.login:req.body.login}) //use async in function definition
then check if existingUser is undefined or null with if statements.
If no user is found return req.next()
If found, we need to check password,
if(req.body.password === existingUser.password){
//return successful
}
I suggest you to double check the next code lines:
mongoose.connect(`mongodb://localhost${listener.address().port}:/register`, {
useNewUrlParser: true,
useUnifiedTopology: true
});
The colon to separate the listening port should go just after 'localhost'...