Can't set headers after they are sent - express.js - angular 4 - node.js

./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

Related

not entering into save function in mongoose

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.

Error thrown creating contacts using mongodb - Can't set headers after they are sent

I get the following error when I'm trying to create contacts with my app
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at ServerResponse.header (/home/bas/Desktop/node-backed/node_modules/express/lib/response.js:767:10)
at ServerResponse.json (/home/bas/Desktop/node-backed/node_modules/express/lib/response.js:264:10)
at /home/bas/Desktop/node-backed/routes/route.js:8:18
at /home/bas/Desktop/node-backed/node_modules/mongoose/lib/model.js:4437:16
at process.nextTick (/home/bas/Desktop/node-` `backed/node_modules/mongoose/lib/helpers/query/completeMany.js:35:39)
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
This is my app.js code
var express= require('express');
var mongoose= require('mongoose');
var bodyparser=require('body-parser');
var cors= require('cors');
var path= require('path');
var app= express();
const route= require('./routes/route');
mongoose.connect('mongodb://localhost:27017/contactlist');
mongoose.connection.on('connected',function(){
console.log('Connected to database mongodb # 27017'); });
app.use(cors()); app.use(bodyparser.json());
app.use(express.static(path.join(__dirname,'public')));
app.use('/api',route);
app.get('/',function(req,res){
res.send('home');
})
app.listen(8080, function(req,res){
console.log('Running');
});
/* https://www.youtube.com/watch?v=wtIvu085uU0 */
This is my router.js code
const express = require('express'); const router= express.Router();
const Contact = require('../models/contact');
router.get('/contacts', function(req, res, next) {
res.send('Retrieving the contact list')
Contact.find(function(err, contacts) {
res.json(contacts);
});
});
router.post('/contact', function(req, res, next) {
let newContact = new Contact({
first_name:req.body.first_name,
last_name:req.body.last_last,
phone:req.body.phone
})
newContact.save(function(err, contacts) {
if(err) {
res.json({ msg: 'Failed to add contact' });
}
else {
res.json({ msg: 'Contact added successfuly' });
}
});
res.send('Post of contacts');
});
router.delete('/contacts/:id', function(req, res, next) {
Contact.remove({ _id: req.params.id }, function(err, result) {
if(err){
res.json(err)
}
else {
res.json(result);
}
})
});
module.exports=router;
This is my contact.js code
const mongoose= require('mongoose'); const ContactSchema =
mongoose.Schema({
first_name:{
type:String,
require:true
},
last_name:{
type:String,
require:true
},
phone:{
type:String,
require:true
} });
const Contact = module.exports = mongoose.model('Contact',ContactSchema);
When I access the url http://localhost:8080/api/contact, it shows the following error
events.js:183
throw er; // Unhandled 'error' event
^
Error: Can't set headers after they are sent.
You're getting this error because, your GET handler sends response to the client twice.
router.get('/contacts', function(req, res, next) {
res.send('Retrieving the contact list') // sending response here once
Contact.find(function(err, contacts) {
res.json(contacts); //attempting to send again
});
});
You should be sending response to the client side only once.
router.get('/contacts', function (req, res, next) {
Contact.find(function (err, contacts) {
if (err) {
return res.json({
msg: err
});
}
res.json({
msg: 'Retrieving the contact list',
contacts: contacts
});
});
});
you should define your middlewares before you define your routes to node, so move these lines :
app.use(cors()); app.use(bodyparser.json());
app.use(express.static(path.join(__dirname,'public')));
after you define you app and before defining const route= require('./routes/route'); , and notice another thing, its better to use promises for your query results, like when you save your model write:
newContact.save().then(()=> res.json('success')}).catch((err)=>{..handle error})
or in your find query:
Contact.find({your ciritica}).then((contacts)=> res.json(contacts)).catch((err)=>{})

TypeError: Cannot read property '_id' of undefined body-parser is installed and required

When I create a new blog post and try to submit it I get the following error: "TypeError: Cannot read property '_id' of undefined"
Here is the code where the "id is undefined"
// CREATE ROUTE
router.post("/", function(req, res){
// Sanitizes blog body to prevent harmful content through it
req.body.blog.body = req.sanitize(req.body.blog.body);
// get data from form and add to blogs array
var title = req.body.title;
var image = req.body.image;
var body = req.body.body;
var author = {
id: req.user._id,
username: req.user.username
};
var newBlog = { title: title, image: image, body: body, author: author};
//Create blog
Blog.create(newBlog, function(err, newlyCreated){
//handle error if can't create post
if(err){
res.render("bposts/new");
//otherwise post it and redirect back to Blog Posts
} else {
console.log(newlyCreated);
res.redirect("/bposts");
}
});
});
The error is being triggered on this line:
var author = {
id: req.user._id,
username: req.user.username
};
I also am posting my models and app.js below. When I did my research on this topic it seemed to all lead back to not being able to parse through req.something.whateverPropertyTryingToParse, or in my case req.user._id. My body parser is installed and saved to package.json file and as you will see is required in my app.js file. I am not sure why it can't parse through the id. Any help and explanation of why this is occurring is appreciated.
blog model:
var mongoose = require("mongoose");
// SCHEMA
var blogSchema = new mongoose.Schema({
title: String,
image: String,
body: String,
created: {type: Date, default: Date.now},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});
//MODEL
module.exports = mongoose.model("Blog", blogSchema);
User Model:
var mongoose = require("mongoose");
var passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: {type: String, unique: true, required: true},
password: String,
// avatar: String,
firstName: String,
lastName: String,
email: {type: String, unique: true, required: true},
// resetPasswordToken: String,
// resetPasswordExpires: Date,
// isAdmin: {type: Boolean, default: false}
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
app.js
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
mongoose = require("mongoose"),
expressSanitizer = require("express-sanitizer"),
passport = require("passport"),
cookieParser = require("cookie-parser"),
LocalStrategy = require("passport-local"),
flash = require("connect-flash"),
session = require("express-session"),
moment = require("moment"),
User = require("./models/user"),
// seedDB = require("./seeds"),
methodOverride = require("method-override");
// APP CONFIG
mongoose.connect("mongodb://localhost/blog", {useMongoClient: true});
//PRODUCTION CONFIG - LIVE URL GOES HERE!
app.set("view engine", "ejs");
app.use(express.static(__dirname + "/assets"));
app.use(bodyParser.urlencoded({extended: true}));
app.use(expressSanitizer());
app.use(methodOverride("_method"));
app.use(cookieParser('secret'));
//require moment
app.locals.moment = require('moment');
// seedDB(); //seed test data!
// PASSPORT CONFIGURATION
app.use(require("express-session")({
secret: "It's a secret to everyone!!",
resave: false,
saveUninitialized: false
}));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(function(req, res, next){
res.locals.currentUser = req.user;
res.locals.success = req.flash('success');
res.locals.error = req.flash('error');
next();
});
// REQUIRE ROUTES
var commentRoutes = require("./routes/comments"),
bpostRoutes = require("./routes/bposts"),
indexRoutes = require("./routes/index");
//USE ROUTES
app.use("/", indexRoutes);
app.use("/bposts", bpostRoutes);
app.use("/bposts/:id/comments", commentRoutes);
//RUN SERVER
app.listen(process.env.PORT, process.env.IP, function(){
console.log("The Server Has Started!");
});
//MIDDLEWARE
var Comment = require('../models/comment');
var Blog = require('../models/blog');
module.exports = {
isLoggedIn: function(req, res, next){
if(req.isAuthenticated()){
return next();
}
req.flash('error', 'You must be signed in to do that!');
res.redirect('/login');
},
checkUserBlog: function(req, res, next){
Blog.findById(req.params.id, function(err, foundBlog){
if(err || !foundBlog){
console.log(err);
req.flash('error', 'Sorry, that Blog does not exist!');
res.redirect('/bposts');
} else if(foundBlog.author.id.equals(req.user._id) || req.user.isAdmin){
req.Blog = foundBlog;
next();
} else {
req.flash('error', 'You don\'t have permission to do that!');
res.redirect('/bposts/' + req.params.id);
}
});
},
checkUserComment: function(req, res, next){
Comment.findById(req.params.commentId, function(err, foundComment){
if(err || !foundComment){
console.log(err);
req.flash('error', 'Sorry, that comment does not exist!');
res.redirect('/bposts');
} else if(foundComment.author.id.equals(req.user._id) || req.user.isAdmin){
req.comment = foundComment;
next();
} else {
req.flash('error', 'You don\'t have permission to do that!');
res.redirect('/bposts/' + req.params.id);
}
});
},
isAdmin: function(req, res, next) {
if(req.user.isAdmin) {
next();
} else {
req.flash('error', 'This site is now read only thanks to spam and trolls.');
res.redirect('back');
}
},
isSafe: function(req, res, next) {
if(req.body.image.match(/^https:\/\/images\.unsplash\.com\/.*/)) {
next();
}else {
req.flash('error', 'Only images from images.unsplash.com allowed.\nSee https://youtu.be/Bn3weNRQRDE for how to copy image urls from unsplash.');
res.redirect('back');
}
}
};
Shouldn't it be
var author = {
id: req.body.user._id,
username: req.body.user.username
};
Can you show the format of the data which you're trying to post?

Unhandled promise Rejection (rejection id: 1) - Node.js

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;

NodeJS: Passport authentication not working

I am using passport local for authentication and the login credentials don't get authenticated. I just get redirected to the failureRedirect. I don't even get the flash error.
Here is my login route:
var express = require('express');
var router = express.Router();
var passport = require('passport');
var flash = require('connect-flash');
router.get('/', function(req, res, next) {
if(req.user){
return res.redirect('/profile');
}
var vm = {
title: 'Login',
error: req.flash('error')
};
res.render('login', { title: 'Place an order' });
});
router.post('/',
passport.authenticate('local', {
failureRedirect: '/login',
successRedirect: '/profile',
failureFlash: 'Invalid credentials'
}));
module.exports = router;
This is app.js:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var passport = require('passport');
var expressSession = require('express-session');
var flash = require('connect-flash');
var config = require('./config');
var routes = require('./routes/index');
var signup = require('./routes/signup');
var login = require('./routes/login');
var profile = require('./routes/profile');
var restrict = require('./auth/restrict');
var passportConfig = require('./auth/passport-config');
passportConfig();
mongoose.connect(config.mongoUri);
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
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(expressSession({
secret: 'themsec',
saveUninitialized: false,
resave: false
}));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.use('/', routes);
app.use('/signup', signup);
app.use('/login', login);
//app.use(restrict);
app.use('/profile', profile);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
Passport-config:
module.exports = function(){
var passport = require('passport');
var passportLocal = require('passport-local');
var userService = require('../services/user-service');
passport.use(new passportLocal.Strategy({username: 'email'},function(email, password, next){
userService.findUser(email, function(err, user){
if(err){
return next(err);
}
if(!user || user.password!= password){
return next(null, null);
}
next(null, user);
});
}));
passport.serializeUser(function(user, next){
next(null, user.email);
});
passport.deserializeUser(function(email, next){
userService.findUser(email, function(err, user){
next(err, user);
});
});
};
User services:
var User = require('../models/user').User;
exports.addUser = function(user, next){
var newUser = new User({
firstName: user.firstName,
lastName: user.lastName,
email:user.email.toLowerCase(),
password: user.password,
});
newUser.save(function(err){
if(err)
return next(err)
next(null);
});
};
exports.findUser = function(email, next){
User.findOne({email:email.toLowerCase()}, function(err, user){
next(err, user)
});
};
User model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userService = require('../services/user-service');
var userSchema = new Schema({
firstName: {type: String, required: true},
lastName: String,
email: {type: String, required: true},
password: {type: String, required: true},
created: {type: Date, default: Date.now}
});
userSchema.path('email').validate(function(value, next){
userService.findUser(value, function(err, user){
if(err){
console.log(err);
return false;
}
next(!user)
});
}, 'That email is already in use');
var User = mongoose.model('User', userSchema);
module.exports = {
User:User
};
Someone please help me, I am turning mad with frustration. I am new to Node.
Edit: I have removed the code that would lead to an infinite loop if the user logged-in, however, I still cannot login.

Resources