CRUD - I can't insert data using express and mongodb - javascript

I am trying to insert a category in the database following the instructions of a course I am taking and I am unable to insert it with the create method. It shows ... loading in Postman and nothing happens and no error message appears on the console. Here are my files.
app.js
const express = require('express')
const mongoose = require('mongoose')
const morgan = require('morgan')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
const expressValidator = require('express-validator')
require('dotenv').config()
//import routes
const authRoutes = require('./routes/auth')
const userRoutes = require('./routes/user')
const categoryRoutes = require('./routes/category')
// app
const app = express()
// db
mongoose.connect(process.env.DATABASE, {
useNewUrlParser: true,
useCreateIndex: true
})
.then(() => console.log('DB Connected'))
// middlewares
app.use(morgan('dev'))
app.use(bodyParser.json())
app.use(cookieParser())
app.use(expressValidator())
// routes middleware
app.use('/api', authRoutes)
app.use('/api', userRoutes)
app.use('/api', categoryRoutes)
const port = process.env.PORT || 8000
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
routes/category.js
const express = require('express')
const router = express.Router()
const { create } = require('../controllers/category')
const { requireSignin} = require('../controllers/category')
const { userById } = require('../controllers/user')
router.post('/category/create/:userId', function(req, res){
requireSignin,
create
});
router.param("userId", userById)
module.exports = router
controllers/category.js
const Category = require("../models/category")
const { errorHandler } = require("../helpers/dbErrorHandler")
exports.create = (req, res) => {
const category = new Category(req.body)
category.save((err, data) => {
if(err) {
return res.status(400).json({
error: errorHandler(err)
})
}
res.json({ data })
})
}
models/category.js
const mongoose = require('mongoose')
const categorySchema = new mongoose.Schema(
{
name: {
type: String,
trim: true,
required: true,
maxlength: 32
}
},
{ timestamps: true }
);
module.exports = mongoose.model('Category', categorySchema)

In order to make sure that data is actually being returned, your create function needs to be asynchronous. Adding async/await to the save function should confirm that you are properly saving the data to the database before returning.

It appears you have an error in your route setup. I assume requireSignin and create should be middleware functions.
So instead of
router.post('/category/create/:userId', function(req, res){
requireSignin,
create
});
you should try this
router.post('/category/create/:userId', requireSignin, create);
// assuming 'create' is the last one, since you are ending the request there
// also assuming that 'requireSignin' is setup as middleware, calling next function

Related

Getting TypeError: User is not a constructor when testing user add with API

I am trying to make my backend work with MongoDB ATLAS.
I'm using express, mongoose and node.js for my tests and when I am trying to test my API routes (in this case to add a user)
The code I have is the following:
users.js
const router = require('express').Router();
const { Router } = require('express');
let User = require('../models/user.model');
router.route('/').get((req, res) => {
User.find()
.then(users => res.json(users))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/add').post((req, res) => {
const username = req.body.username;
const newUser = new User({username});
newUser.save()
.then(() => res.json('User added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
module.exports = router
user.model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3
},
}, {
timestamps: true,
});
const User = mongoose.model('User', userSchema);
module.exports = User;
server.js
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true, useCreateIndex: true }
);
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDB database connection established successfully");
})
const exercisesRouter = require('./routes/exercises');
const usersRouter = require('./routes/users');
app.use('/exercises', exercisesRouter);
app.use('/users', usersRouter);
app.listen(port, () => {
console.log(`Server is running on port: ${port}`);
});
When I am testing this with postman via a POST I get the following error: I am getting the following error: TypeError: User is not a constructor
The post is done to http over port 5000 with raw json body as "username": "blahblahblah"
Can you help with this maybe?
I am not sure what happened but today I cut and pasted back all the code and the API started to work just fine. Now I can add users without any problems.
Could be a glitch but not sure at this point.

CORS issue with Express Router end points

I have a react app that is making a REST to a an express node server.
The express router defines a bunch of rest endpoints.
When I hit the endpoints in the express router using postman, it works fine.
When I hit the endpoint with me react app, it doesn't. I'm seeing 400 error when my react app makes the call using axios.
This is what my index.js looks like:
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const cors = require("cors");
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
// server.use(bodyParser.json());
app.use(cors());
// app.options("*", cors());
const UserModel = require("./models/User");
mongoose
.connect(
"mongodb"
)
.then(() => console.log("SUCESSFULLY connected to MongoDB!"))
.catch((error) => console.log(`FAILED tot connect to MongoDB: ${error}`));
require("./auth/localStrategyAuth");
const authRoutes = require("./routes/authRoutes");
app.use("/v1", authRoutes);
// app.post("/", (req, res) => {
// res.send("Hello World!");
// });
// app.post("/v1/signup", (req, res) => {
// console.log("lol");
// });
// app.use(express.json());
const PORT = 5000;
app.listen(PORT, () =>
console.log(`ui-rest listening on port localhost:${PORT}`)
);
user.js
const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const { Schema } = mongoose;
const UserSchema = new Schema({
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
});
const UserModel = mongoose.model("user", UserSchema);
module.exports = UserModel;
authRoutes.js
const express = require("express");
const passport = require("passport");
const jwt = require("jsonwebtoken");
const JWTstrategy = require("passport-jwt").Strategy;
//We use this to extract the JWT sent by the user
const ExtractJWT = require("passport-jwt").ExtractJwt;
const router = express.Router();
// When the user sends a post request to this route, passport authenticates the user based on the
// middleware created previously
router.post(
"/signup",
passport.authenticate("signup", { session: false }),
async (req, res, next) => {
res.json({
message: "Signup successful",
user: req.user,
});
}
module.exports = router;
localStrategyAuth.js
const passport = require("passport");
const localStrategy = require("passport-local").Strategy;
const UserModel = require("../models/User");
//Create a passport middleware to handle user registration
passport.use(
"signup",
new localStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
// Save the information provided by the user to the the database
const user = await UserModel.create({ email, password });
// Send the user information to the next middleware
return done(null, user);
} catch (error) {
done(error);
}
}
)
);
This is what my express router looks like:
const express = require("express");
const router = express.Router();
router.post(
"/signup",
passport.authenticate("signup", { session: false }),
async (req, res, next) => {
res.json({
message: "Signup successful",
user: req.user,
});
}
);
module.exports = router;
What am I missing? I've set up CORS in the index.js file. I just can't see where I'm going wrong. Why cant my react app hit the express router endpoints.
If I have a normal express endpoint, then my react app is able to hit those endpoints. For example, the endpoint below works fine when my react app hits it.
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
app.post("/", (req, res) => {
res.send("Hello World!");
});
const PORT = 5000;
app.listen(PORT, () =>
console.log(`listening on port localhost:${PORT}`)
app.post("/someSignup", (req, res) => {
console.log("signup");
});
I've also tried things like with no luck:
const authRoutes = require("./routes/authRoutes");
authRoutes.use(cors());
Here is what my react code looks like when it submits the rest call:
// axios setup
axios.create({
baseURL: "http://localhost:5000",
// headers: {
// "Content-Type": "application/json",
// },
});
// Handle submit
handleSubmit = async (event) => {
event.preventDefault();
const newUserData = {
// firstName: this.state.firstName,
// lastName: this.state.lastName,
email: this.state.email,
password: this.state.password,
};
const result = await axios.post("/v1/signup", newUserData);
console.log(result);
};
Here is a screenshot of headers tab on chrome console
Here is a screenshot of response tab on chrome console
Here is a screenshot of the request
400 means bad request, your problem isn't about with cors.
You didn't setup your api to handle JSON data which react sends, so it can't read your request.body and gives 400-Bad Request.
So you need to add this line:
app.use(bodyParser.json());
Also in the current versions of express, body parser isn't required , it comes with express. So you can use it like this:
app.use(express.json());
The reason it worked with postman is that you sent the data in x-www-form-urlencoded.
you can use check my code for cors error.
const express = require('express');
var mongoose = require('mongoose');
const bodyParser = require('body-parser');
var morgan = require('morgan');
var cors = require('cors')
const app = express();
// CORS Middleware
app.use(cors());
// Logger Middleware
app.use(morgan('dev'));
// Bodyparser Middleware
app.use(bodyParser.json());
const MongoClient = require('mongodb').MongoClient;
const uri = "uri";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
client.connect(err => {
console.log('MongoDB Connected...')
const collection = client.db("dbname").collection("collectionname");
app.post('/name', (req, res) => {
collection. insertOne({ name: req.body.name })
res.send("data added")
});
});
const port = process.env.PORT || 5000;
app.listen(port, function () {
console.log(`Example app listening on port ${port}`);
});
You need to register the cors middleware into express app.
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
app.use(cors());
app.post("/", (req, res) => {
res.send("Hello World!");
});
const PORT = 5000;
app.listen(PORT, () => console.log(`listening on port localhost:${PORT}`)

Why does save function in express not work?

This is my first day in express. I was trying to create a simple route but my save function doesn't seem to work. I tried looking at similar questions posted on stackoverflow but couldn't make it. Any help will be appreciated.
const express = require("express");
const router = express.Router();
const Post = require("../models/Post");
//ROUTES
router.post('/', (req, res) => {
const post = new Post({
title: req.body.title,
description: req.body.description
})
post.save()
.then(data => {
res.json(data);
})
.catch(err => {
res.json(err);
});
});
module.exports = router;
And here is my model.
const mongoose = require("mongoose");
const PostSchema = mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
}
});
module.exports = mongoose.model('Posts',PostSchema);
app.js code
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
require("dotenv/config");
//IMPORT ROUTES
const postsRoute = require("./routes/posts");
//MIDDLEWARE - Function that always execute when routes are being hit.
app.use(bodyParser.json())
app.use('/posts', postsRoute)
//app.use('/users', usersRoute)
//ROUTES
app.get('/', (req, res) => {
res.send("We are on home");
});
//CONNECT TO DB
mongoose.connect(
process.env.DB_CONNECTION,
{ useNewUrlParser: true },
() => {
console.log("DB Connected!!")
})
//How do we start listening to the server
app.listen(3000);
My postman query -
Postman Response -
Please let me know if you need any more information.
your app.js should be :
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
require("dotenv/config");
//MIDDLEWARE - Function that always execute when routes are being hit.
app.use(bodyParser.json())
mongoose.connect(process.env.DB_CONNECTION, { useNewUrlParser: true }, function(err) {
if (err) {
console.error('System could not connect to mongo server')
console.log(err)
process.exit()
} else {
console.log('System connected to mongo server')
}
});
//ROUTES
app.get('/', (req, res) => {
res.send("We are on home");
});
//IMPORT ROUTES
const postsRoute = require("./routes/posts");
app.use('/posts', postsRoute)
app.listen(3000);
also add console log in router to check req.body :
router.post('/', (req, res) => {
console.log('req.body===',req.body);
...
});

Node JS Type Error : Cannot read property

I am a beginner nodejs developer, and for a start I decided to develop a blog project for practice. I am using Nodejs Express and native js on the client. When adding a post, nodejs throws an error in the routes:
(node: 25967) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'title' of undefined
at router.post (/routes/post.js:15:25)
Here is my code:
routes/post.js
const express = require('express');
const router = express.Router();
const Post = require('../models/Post');
// http://localhost:5000/api/post (GET)
router.get('/', async (req, res) => {
const posts = await Post.find({})
res.status(200).json(posts)
})
// http://localhost:5000/api/post (POST)
router.post('/', async (req, res) => {
const postData = {
title: req.body.title,
text: req.body.text
}
const post = new Post(postData)
await post.save()
res.status(201).json(post)
})
// http://localhost:5000/api/post/id (DELETE)
router.delete('/:postId', async (req, res) => {
await Post.remove({_id: req.params.PostId})
res.status(200).json({
message: 'Deleted'
})
})
module.exports = router
app.js
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser')
const mongoose = require('mongoose');
const postRouter = require('./routes/post');
const keys = require("./keys");
const port = process.env.PORT || 5000;
const clientPath = path.join(__dirname, 'client');
const app = express();
app.use(express.static(clientPath))
app.use('/api/post', postRouter)
app.use(bodyParser.json())
mongoose.connect(keys.mongoURI, { useNewUrlParser: true,
useUnifiedTopology: true, useCreateIndex: true })
.then(() => console.log('MongoDB connected'))
.catch( err => console.error(err));
app.listen(port, () => {
console.log(`Server has been started on port ${port}`);
});
(model)Post.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const postSchema = new Schema ({
title: {
type: String,
required: true,
},
text: {
type: String,
required: true
},
date : {
type: Date,
default: Date.now
}
})
module.exports = mongoose.model('posts', postSchema)
what could be the problem?
This is an ordering problem, switch these lines around:
app.use('/api/post', postRouter)
app.use(bodyParser.json())
Express middlewere are run in order, which in your case means your post route will be called before the bodyParser middleware is able to parse the JSON body.

Send Arraydata from the from react to node. and save it in mongoose

I am trying to send an array from react using axios to my Node.js file, however I am getting an status 404 error.
My profileSchema as follows:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// Create Schema
const ProfileSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: "users"
},
preference: [
{
type: String
}
],
date: {
type: Date,
default: Date.now
}
});
module.exports = Profile = mongoose.model("profile", ProfileSchema);
I want to send an array to the back end with an axios request.
for example
tempArray=["Chocoloate","Vanilla","Strawberry"]
and the axios request I make is
axios
.post('/api/profile/register', tempArray)
.then(res => console.log(res.data))
.catch(err => console.log(err));
My profile.js look list this. I also have body-parse and all installed.
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const passport = require("passport");
const Profile = require("../../models/Profile");
// Load User Model
const User = require("../../models/User");
router.get("/test", (req, res) => res.json({ msg: "Profile Works" }));
// #route POST api/profile
// #desc Create or edit user profile
// #access Private
router.post(
"/register",
(req, res) => {
console.log(req);
var list = req.body;
console.log(list);
}
);
However, I am still getting 404 errors and not being able to save the array to the backend
index.js file
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const users = require("./routes/api/users");
const profile = require("./routes/api/profile");
const posts = require("./routes/api/posts");
const issues = require("./routes/api/issues");
const mp = require("./routes/api/mp");
const app = express();
// Body parser 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)
.then(() => console.log("MongoDB Connected"))
.catch(err => console.log(err));
// Passport middleware
app.use(passport.initialize());
// Passport Config
require("./config/passport")(passport);
// Use Routes
app.use("/api/users", users);
app.use('/api/profile', profile);
app.use("/api/posts", posts);
app.use("/api/issues", issues);
app.use("/api/mp", mp);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server running on port ${port}`));
Always try sending the post body as an object.
tempArray = ['a', 'b', 'c']
axios
.post('/api/profile/register', {tempArray: tempArray})
.then(res => console.log(res.data))
.catch(err => console.log(err));
and the body params in the router.post as
router.post('/register/', function(req, res,next) {
const tempArray = req.body.tempArray;
//perform your query operations here and pass tempArray as params to your query
})

Categories