I am newbie to node js and mongoose and unable to save the record in the mongoose I am using Mongodb atlas I have tried several ways to debug and tried different things but not getting save or not able enter into the inside the save function. so not able to handle the save callback in moongose If try to hit request in postman its not getting the response it getting blocked and not entering into save so Thanks in Advance
controller.js
const mongoose = require('mongoose');
const User = require('../models/users');
exports.registerUser = (req,res,next)=>{
console.log(req.body);
const user = new User({
_id:mongoose.Types.ObjectId(),
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email
});
user.save(function(err) {
console.log("Callback");
if (err) {
console.log("error");
res.json({message: err});
}
else{
res.json({ message: 'User created' });
}
})
}
router.js
const mongoose = require('mongoose');
const User = require('../models/users');
exports.registerUser = (req,res,next)=>{
console.log(req.body);
const user = new User({
_id:mongoose.Types.ObjectId(),
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email
});
user.save(function(err) {
console.log("Callback");
if (err) {
console.log("error");
res.json({message: err});
}
else{
res.json({ message: 'User created' });
}
})
}
model.js
const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
firstName: {type: String, required: true},
lastName: {type: String, required: true},
email: {type: String, required: true}
});
module.exports = mongoose.model('User', userSchema);
app.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const userRoutes = require('./api/routes/users');
const MongoClient = require('mongodb').MongoClient;
const uri = "mongodb+srv://<connection string>/admin";
const client = new MongoClient(uri, { useNewUrlParser: true });
client.connect(err => {
});
mongoose.Promise = global.Promise;
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use((req,res,next )=>{
console.log(req);
res.header("Access-Control-Allow-Origin", "*");
if (req.method === "OPTIONS") {
res.header("Access-Control-Allow-Methods", "PUT, POST, PATCH, DELETE, GET");
return res.status(200).json({});
}
next();
});
app.use('/', userRoutes);
app.use((req,res,next)=>{
const error = new Error('Not Found');
error.status = 404;
next(error);
});
app.use((error,req,res,next)=>{
res.status(error.status || 500);
res.json({
error:{
message: error.message
}
})
});
module.exports = app;
Are you sure mongoose is using any connections? Seems like you connected to server with mongodb module instead. See the Getting Started docs on how to connect with mongoose.
Related
I am trying to send a post request and dealing with this error "Cannot POST /". What can be the problem? I am using a Postman to send a Post request to our server. My post request is
localhost:4000
Here is my index.js code:
const Joi = require('joi');
Joi.objectId = require('joi-objectid')(Joi);
const mongoose = require('mongoose');
const users = require('./routes/users');
const express = require('express');
const app = express();
mongoose.connect('mongodb://localhost/mongo-games')
.then(() => console.log('Now connected to MongoDB!'))
.catch(err => console.error('Something went wrong', err));
app.use(express.json());
app.use('/api/users', users);
const port = process.env.PORT || 4000;
app.listen(port, () => console.log(`Listening on port ${port}...`));
And here is my user.js code:
const Joi = require('joi');
const mongoose = require('mongoose'); //needed for validation & creating user mongodb schema
const User = mongoose.model('User', new mongoose.Schema({
name: {
type: String,
required: true,
minlength: 5,
maxlength: 50
},
email: {
type: String,
required: true,
minlength: 5,
maxlength: 255,
unique: true
},
password: {
type: String,
required: true,
minlength: 5,
maxlength: 1024
}
}));
function validateUser(user) {
const schema = {
name: Joi.string().min(5).max(50).required(),
email: Joi.string().min(5).max(255).required().email(),
password: Joi.string().min(5).max(255).required()
};
return Joi.validate(user, schema);
}
exports.User = User;
exports.validate = validateUser;
And my users.js code:
const { User, validate } = require('../models/user');
const express = require('express');
const router = express.Router();
router.post('/', async (req, res) => {
// First Validate The Request
const { error } = validate(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
// Check if this user already exisits
let user = await User.findOne({ email: req.body.email });
if (user) {
return res.status(400).send('That user already exisits!');
} else {
// Insert the new user if they do not exist yet
user = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password
});
await user.save();
res.send(user);
}
});
module.exports = router;
What am I missing here? Any ideas?
Your middleware is- app.use('/api/users', users);
and your post is about that route.
In your postman> URL > you need to write localhost:4000/api/users.
because this is the URL that gets to the router.
Make sure that you are sending request to the /api/users. Looks like you are trying to send it to / which you are not handling.
I'm trying to set up an API with MongoDB (Mongoose) with a JWT authentication. I am at the first step where I create an user in the DB.
But I encounter a problem : the async/await taking so long and never ending, while the user is not created on DB. I don't know why.
I'm testing with POSTMAN for requests. For information, when I'm starting my app, I'm getting the "connected to db !" who appear correctly.
Can someone help me please ?
app.js
'use strict';
const express = require("express"),
app = express(),
authRoutes = require('./routes/auth'),
externalRoutes = require('./routes/web'),
database = require('./database/db'),
bodyParser = require("body-parser"),
mongoose = require('mongoose')
;
require('dotenv').config();
var options = { useNewUrlParser: true, useUnifiedTopology: true };
mongoose.connect("mongodb+srv://user:password#host.mongodb.net/test?retryWrites=true&w=majority", options, () => console.log('connect to db !'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('/api/user', authRoutes);
app.use('/', externalRoutes);
app.listen(8080);
auth.js
const router = require('express').Router();
const User = require('../database/schemas/User');
router.post('/register', async (req, res) => {
const user = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password,
});
const savedUser = await user.save((error, userDoc) => {
if (error) return res.status(400).send(error);
});
res.send({
user: savedUser._id
});
}).post('/login', (req, res) => {
});
module.exports = router;
User.js
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
min: 6,
max: 255
},
email: {
type: String,
required: true,
max: 255,
min: 10
},
password: {
type: String,
required: true,
max: 1024
},
createdAt: {
type: Date,
default: Date.now()
},
updatedAt: {
type: Date,
default: Date.now()
},
});
module.exports = mongoose.model('User', userSchema);
In Auth.js do this instead
const router = require('express').Router();
const User = require('../database/schemas/User');
router.post('/register', async (req, res) => {
const user = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password,
});
try {
// if you are using await, don't pass it a callback
const savedUser = await user.save();
return res.send({
user: savedUser._id
});
} catch (error) {
// use try/catch to handle error instead of error first parameter in callback
return res.status(400).send(error);
}
}).post('/login', (req, res) => {
});
module.exports = router;
Here is a link to the documentation that shows you how to correctly use the save method. https://mongoosejs.com/docs/api.html#model_Model-save
I'm trying to create a CRUD REST API in NodeJS, Express, and Mongodb.
I did something to break all my routes where they no longer return responses. No errors, nothing in the console, etc. I'm not sure what happened, I had it working before. Through just some console.logs I figured out it was freezing whenever it interfaced with the database.
Now, when I send a post request in Postman, it just hangs with 'Loading request'. I'm sending my request as a raw JSON in the body and a content type of application/json; charset=UTF-8 in the header.
{"username":"zezimaUsername","rsn":"Zezima","avatar":"http://secure.runescape.com/m=avatar-rs/Zezima/chat.png"}
They seem to all be hanging once they interact with Mongodb. I have Mongodb running locally with the mongod --port 27017 and created my database with two collections (user and posts) in Mongodb Compass.
I setup my db in a db.js file...
var mongoose = require('mongoose');
var url = 'mongodb://localhost:27017/my-group';
mongoose.connect(url);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error: '));
module.exports = db;
And start my app with my server.js...
var express = require('express');
var api = require('./api');
var app = express();
app.use(express.json());
app.use('/api', api);
//Error handling, don't return stack trace to user, log in console.
app.use(function (err, req, res, next){
console.log(err.stack);
res.status(500).send('Something went wrong, internal server error.');
});
app.listen(3000, function(){
console.log("Listening on port 3000");
});
And define my routes in my api.js file...
var express = require('express');
var router = express.Router();
var User = require('./db/models/User');
var Post = require('./db/models/Post');
router.post('/register', function(req, res){
var user = new User(req.body);
user.save()
.then(function(item){
res.status(200).send({message: "User successfully created.", status: 200});
})
.catch(function(err){
res.status(400).send({message: "User failed to save to database", status: 400});
});
});
router.get('/user/:username', function(req, res){
var query = User.findOne({"username": req.params.username});
query.exec(function(err, user){
if(user === null){
res.status(404).send({message: "User not found", status: 404});
}else{
res.status(200).send(user);
}
});
});
router.post('/create_post', function(req, res){
var post = new Post(req.body);
post.save()
.then(function(item){
res.status(200).send({message: "Post successfully created.", status: 200});
})
.catch(function(err){
console.log(err);
res.status(400).send({message: "Post failed to save to database", status: 400});
});
});
router.get('/post/id/:id', function(req, res){
var query = Post.findOne({"_id":req.params.id});
query.exec(function(err, post){
if(post === null){
res.status(404).send({message: 'Post not found', status: 404});
}else{
res.status(200).send(post);
}
});
});
router.get('/post/boss/:boss', function(req, res){
var query = Post.find({"boss":req.params.boss});
query.exec(function(err, post){
if(post === null){
res.status(404).send({message: 'Post not found', status: 404});
}else{
res.status(200).send(post);
}
});
});
module.exports = router;
And just to be complete...my models look like...
User.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
username:{
type: String,
required: true
},
rsn:{
type: String,
required: true
},
avatar:{
type: String,
required: true
},
posts:[{
type: Schema.Types.ObjectId,
ref: 'posts'
}]
});
var user = mongoose.model('users', userSchema);
module.exports = user;
and Post.js
var mongoose = require('mongoose');
var shortid = require('shortid');
var Schema = mongoose.Schema;
var postSchema = new Schema({
_id:{
type: String,
default: shortid.generate
},
username:{
type: Schema.Types.ObjectId,
ref: 'users'
},
rsn:{
type: String,
required: true
},
avatar:{
type: String,
required: true
},
boss:{
type: String,
required: true
}
});
var post = mongoose.model('posts', postSchema);
module.exports = post;
I'm not sure what's happening, I keep reading a bunch of various tutorials and the documentation but I'm just not seeing the issue I'm having.
You have not required your db.js file in your server.js file.
Require it after var express = require('express');
let db = require("./db");
Then it will work fine.
./models/user.js
var mongoose = require('mongoose');
var validator = require('mongoose-unique-validator');
var Schema = mongoose.Schema;
const schema = new Schema({
firstName:{ type: String, required: true },
lastName: {type: String, required: true},
password: {type: String, required: true},
email: {type: String, required: true, unique: true },
transactions: [{type: Schema.Types.ObjectId, ref: 'Transaction'}]
});
schema.plugin(validator);
module.exports = mongoose.model('User', schema);
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var appRoutes = require('./routes/app');
var userRoutes= require('./routes/user');
var app = express();
mongoose.connect('localhost:27017/remake');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PATCH, DELETE, OPTIONS');
next();
});
app.use('/user', userRoutes);
app.use('/', appRoutes);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
return res.render('index');
});
module.exports = app;
'./routes/item.js'
var express = require('express');
var router = express.Router();
const mongoose = require('mongoose');
const User = require('../models/user');
const bcrypt = require('bcryptjs');
router.post('/', function(req, res, next) {
User.findOne({email: req.body.email}, (err, user) => {
if(err){
return res.status(500).json({
title: 'An error has occured',
error: err
});
}
if(user){
return res.status(401).json({
title: 'Email already taken!',
error: {message: 'Email already taken!'}
});
}
});
const user = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
email : req.body.email,
password: bcrypt.hashSync(req.body.password, 10)
});
user.save( (err, result) => {
if(err){
return res.status(500).json({
title: 'An error has occured',
error: err
});
}
res.status(201).json({
title: 'User created!',
obj: result
});
});
});
module.exports = router;
It's fine every time I create a user - but as soon I create a user with the same email it would throw this error.
> _http_outgoing.js:504
> throw new Error('Can\'t set headers after they are sent.');
> ^
>
> Error: Can't set headers after they are sent.
> at validateHeader (_http_outgoing.js:504:11)
> at ServerResponse.setHeader (_http_outgoing.js:511:3)
> at ServerResponse.header (/Users/sean/Angular/appdev-remake/node_modules/express/lib/response.js:719:10)
> at ServerResponse.send (/Users/sean/Angular/appdev-remake/node_modules/express/lib/response.js:164:12)
> at ServerResponse.json (/Users/sean/Angular/appdev-remake/node_modules/express/lib/response.js:250:15)
> at Query.User.findOne (/Users/sean/Angular/appdev-remake/routes/user.js:16:36)
> at /Users/sean/Angular/appdev-remake/node_modules/kareem/index.js:177:19
> at /Users/sean/Angular/appdev-remake/node_modules/kareem/index.js:109:16
> at _combinedTickCallback (internal/process/next_tick.js:95:7)
> at process._tickCallback (internal/process/next_tick.js:161:9)
I already put return statements for every instance I could find - is this an express/mongo bug or is there something wrong with my code. I've previously coded this REST API and put them side to side, they're literally the same but this one won't work.
Your calling user.save outside of the scope of the callback of User.findOne
See below - I have put the creation of a user inside the User.findOne callback:
router.post('/', function(req, res, next) {
User.findOne({email: req.body.email}, (err, user) => {
if(err){
return res.status(500).json({
title: 'An error has occured',
error: err
});
}
if(user){
return res.status(401).json({
title: 'Email already taken!',
error: {message: 'Email already taken!'}
});
}
//this is inside the callback
const user = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
email : req.body.email,
password: bcrypt.hashSync(req.body.password, 10)
});
user.save( (err, result) => {
if(err){
return res.status(500).json({
title: 'An error has occured',
error: err
});
}
return res.status(201).json({
title: 'User created!',
obj: result
});
});
});
});
In your code, the return is effectively being called twice, hence the error
I'm new to Node.js and trying to figure out of some problems.
I've defined a signup function on a Node.js server for an Android app who writes user's info on MongoDB.
server.js
var express = require('express'),
app = express(),
port = process.env.PORT || 3000,
mongoose = require('mongoose'),
Task = require('./api/models/serverModel'),
bodyParser = require('body-parser');
var url = "mongodb://localhost:27017/ProjectDB";
mongoose.Promise = global.Promise;
mongoose.connect(url);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var routes = require('./api/routes/serverRoute');
routes(app);
app.listen(port);
console.log('Project RESTful API server started on: ' + port);
serverModel
var UserSchema = new mongoose.Schema({
userName: {type: String, unique: true, required: true},
email: {type: String, unique: true, required: true},
password: {type: String, required: true},
createdAt: {type: String, required: true}
});
var User = mongoose.model('User', UserSchema);
module.exports = User;
serverRoute
module.exports = function(app) {
var Project = require('../controllers/serverController');
// Project Routes
app.route('/signup')
.post(Project.signup);
};
serverController
...
mongoose.Promise = global.Promise;
exports.signup = function(req, res) {
return new Promise( function(resolve,reject) {
var user = new User({
userName: req.body.name,
password: req.body.pass,
mail: req.body.email,
createdAt : new Date()
});
user.save()
.then(function() { resolve({ status: 201, message: 'User Registered Successfully !' })})
.catch(function(err) {
if (err.code == 11000) {
reject({ status: 409, message: 'User Already Registered !' });
} else {
reject({ status: 500, message: 'Internal Server Error !' });
}
});
})};
...
It compiles without any error.
When I try to send a JSON via Postman like this:
{
"userName" : "username",
"email" : "user.name#gmail.com",
"password" : "blabla1"
}
it reports
UnhandledPromiseRejectionWarning: Unhandled promise Rejection (rejection id: 1) [object Object]
I've read tons of posts but I can't get out of this.
Any help?
Thanks.
Try this and revert.
server.js
var express = require('express'),
app = express(),
port = process.env.PORT || 3000,
mongoose = require('mongoose'),
Task = require('./api/models/serverModel'),
bodyParser = require('body-parser');
var url = "mongodb://localhost:27017/ProjectDB";
mongoose.Promise = global.Promise;
mongoose.connect(url);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var routes = require('./api/routes/serverRoute');
//change
//routes(app);
app.use('/',routes);
app.listen(port);
console.log('Project RESTful API server started on: ' + port);
serverRoute
var express = require('express');
var router = express.Router();
// GET home page.
router.post('/signup', function(req, res, next) {
var Project = require('../controllers/serverController');
Project.signup().then(function(result){
res.send(result);
}).catch(function(err){
res.send(err);
});
});
module.exports = router;