Switching from Localhost MongoDB, to deploying on Heroku with MongoLab - mongodb

I'v build an app on my local machine using MongoDB, and this is fully working locally. But once I deploy it to Heroku I cannot connect to the DB or retrieve anything from the REST service. I'v read the docs many time and noticed they need to be updated in many places which is throwing me off. Here is my initialize code:
Any help or suggestions much appreciated.
"use strict";
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 server = express();
server.set("port", (process.env.PORT || 5000));
server.use(express.static(__dirname + "/public"));
server.listen(server.get("port"), function() {
console.log("Node server is running at localhost:" + server.get("port"));
});
var router = express.Router();
/* GET home page. */
router.get("public", function(req, res) {
res.render("index", { title: "MyApp" });
});
module.exports = router;
// **** LocalDB: "mongodb://localhost:27017/myapp" ****
var mongo = require("mongoskin");
var db = mongo.db("mongodb://xxxxxx:xxxxxx#ds045511.mongolab.com:45511/xxxxxx", {native_parser:true});
var routes = require("./routes/index");
var users = require("./routes/users");
var divesites = require("./routes/myCollection");
var app = express();
// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "jade");
// uncomment after placing your favicon in /public
//app.use(favicon(__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")));
// Make our db accessible to our router
app.use(function(req,res,next){
req.db = db;
next();
});
app.use("/", routes);
app.use("/users", users);
app.use("/myCollection", myCollection);
// 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;

You could use the environment variable process.env.MONGOLAB_URI instead and see how that goes:
var mongo = require("mongoskin");
var db = mongo.db(process.env.MONGOLAB_URI, {native_parser:true});

Related

Error 404 Not Found Using Pug & Express and MongoDB

I am getting at 404 not found error using Express & MongoDB for a POST request. I tried to redo my routes numerous times, but am having trouble with the login page. I want to POST the information to my server and render a simple "Welcome Message."
Please advise.
Routes Folder:
var express = require('express');
var router = express.Router();
let mongoose = require('mongoose');
var User = require('../models/users')
//Get registration page from index button//
router.get('/register', function(req, res, next) {
res.render('register');
if (err) return console.error(err);
res.json(user);
});
//Post user data to database POST /register //
router.post('/register', function(req, res, next) {
res.render('Welcome to Fit 7');
})
var username = req.body.username;
var email = req.body.email;
var password = req.body.password;
var newuser = new User();
newuser.username = username;
newuser.email = email;
newuser.password = password;
newuser.save(function(err, savedUser) {
if(err) {
console.log(err);
return res.status(500).send();
}
return res.status(200).send();
})
module.exports = router;
App JS Code:
// var createError = require('http-errors');
var express = require('express');
var app = express();
var path = require('path');
// var cookieParser = require('cookie-parser');
var logger = require('morgan');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var pug = require('pug');
// var indexRouter = require('./routes/index');
var workouts = require('./routes/workouts');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
// view engine setup
app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));
// app.use(cookieParser());
// app.use(express.static(path.join(__dirname, 'public')));
// app.use('/', indexRouter);
// app.use('/api/workouts', workouts);
app.get('/', function (req, res) {
res.render('index')
})
//Registration Route for New Users
app.get('/register', function (req, res) {
res.render('register')
});
app.get('/home', function (req, res) {
res.render('home');
});
app.get('/workout/new', function (req, res) {
res.render('workoutform');
});
// 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 handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Pug Template Code:
body(data-gr-c-s-loaded='true', style='')
.container
form(action='/register', method='post').form-signin
h1.form-signin-heading Login to Fit-7
label.sr-only(for='username') Name
input#name.form-control(type='username', placeholder='username',
required='', autofocus='')
label.sr-only(for='email') Email address
input#inputEmail.form-control(type='email', placeholder='email address',
required='', autofocus='')
label.sr-only(for='password') Password
input#password.form-control(type='password', placeholder='password',
required='')
button.btn.btn-lg.btn-primary.btn-block(type='submit') Sign in
span._hsShareImage.hsShareImage  
loom-container#lo-engage-ext-container
loom-shadow(data-reactroot='', classname='resolved')
You dont seem to import the router anywhere in your app.js. First add
var registerRoute = require("./path/to/route.js");
after your other requires. Then add
app.use(registerRoute)
in place of this line:
app.get('/register', function (req, res) {
res.render('register')
});
I still dont have a reputation to like the comment above or comment, but the answer was very helpful.
But my problem was that I had the bellow line:
app.use('/', routes);
So I changed to where my application was
app.use('/Live/api', routes);
I'm using express with pug

API that fetches all records from mongoDB using express and mongoskin driver

I am beginner in Mean stack I am developing an API that fetches all records from mongodb using express. But I am not able to fetch all records from the database. I can't figure what I am doing wrong, I am doing it as follows:
This is my main app (server.js)
require('rootpath')();
var express = require('express');
var app = express();
var session = require('express-session');
var bodyParser = require('body-parser');
var expressJwt = require('express-jwt');
var config = require('config.json');
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(session({
secret: config.secret,
resave: false,
saveUninitialized: true
}));
// use JWT auth to secure the api
app.use('/api', expressJwt({
secret: config.secret
}).unless({
path: ['/api/users/authenticate', '/api/users/register']
}));
// routes
app.use('/', require('./controllers/login.controller'));
app.use('/register', require('./controllers/register.controller'));
app.use('/app', require('./controllers/app.controller'));
app.use('/api/users', require('./controllers/api/users.controller'));
/*// make '/app' default route
app.get('/', function (req, res) {
return res.redirect('/app');
});*/
// start server
var server = app.listen(3000, function() {
console.log('Server listening at http://' + server.address().address + ':' + server.address().port);
});
This is my user.controller.js user will make a request to the api
http://localhost:3000/api/users/userList
var express = require('express');
var router = express.Router();
var userService = require('services/user.service');
router.get('/userList', getUserList);
module.exports = router;
function getUserList(req, res) {
userService.userList()
.then(function(users) {
if (users) {
res.send(users);
} else {
res.sendStatus(404);
}
})
.catch(function(err) {
res.status(400).send(err);
});
}
This is my user.service.js where I am querying the database to fetch all records using mongoskin driver.
var Q = require('q');
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/EmployeeForm", {
native_parser: true
});
db.bind('users');
var service = {};
service.userList = userList;
module.exports = service;
function userList() {
var deferred = q.defer();
db.users.find(function(err, users) {
if (err) deferred.reject(err.name + ': ' + err.message);
});
return deferred.promise;
}
So i think it's find issue.
MongoDB find method return cursor by default.
https://docs.mongodb.com/manual/reference/method/db.collection.find/
From https://github.com/kissjs/node-mongoskin they use method toArray which will transform cursor into array of objects like this
db.find.toArray(callback)
So try like this in userList()
function userList() {
var deferred = q.defer();
db.users.find({}).toArray(function(err,docs){
err ? deferred.reject(err) : deferred.resolve(docs);
});
return deferred.promise;
}
Hope this helps.

Nodejs/Express Session - Error: Can't set headers after they are sent

I am getting the below error while trying to use express session with a simple nodejs sample app.
When "resave" is set to true the below error appears, however when the same is set to false, there is no error.
GET / 304 13.380 ms - - Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
at ServerResponse.header
(/Volumes/SURESH/GSKLabs/NodeApp/node_modules/express/lib/response.js:718:10)
at ServerResponse.contentType
(/Volumes/SURESH/GSKLabs/NodeApp/node_modules/express/lib/response.js:551:15)
at ServerResponse.send
(/Volumes/SURESH/GSKLabs/NodeApp/node_modules/express/lib/response.js:138:14)
at done
(/Volumes/SURESH/GSKLabs/NodeApp/node_modules/express/lib/response.js:957:10)
Below is the code app.js
var express = require('express');
var session = require('express-session');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongojs = require('mongojs');
var mongoStore = require('connect-mongo')(session);
var db = mongojs('mongodb://localhost:27017/checker', ['sessions']);
var routes = require('./routes/index');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
var sessionStore = new mongoStore({
db: db,
})
// Session details
app.use(session({
secret: 'check first',
name: {secure: true, maxAge: 60000},
store: sessionStore, // connect-mongo session store
proxy: true,
resave: true,
saveUninitialized: true
}));
// 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('/', routes);
// 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/Volumes/SURESH/GSKLabs/NodeApp/node_modules/express/lib/router/index.js:310:13
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;
routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
package.json
{
"name": "NodeApp",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.15.1",
"connect-mongo": "^1.3.2",
"cookie-parser": "~1.4.3",
"debug": "~2.2.0",
"ejs": "~2.4.1",
"express": "~4.13.4",
"express-session": "^1.14.1",
"mongojs": "^2.4.0",
"morgan": "~1.7.0",
"serve-favicon": "~2.3.0"
}
}
As per my understanding, since the resave:true, express session trying to set the cookie after the response is already sent. Cannot change to resave:false, as it needs to be "true" for using rolling option in express session.
Any help how to solve this error in the above sample code. Thanks.

How to separate the routes and database functionality from appRouter.js using NodeJS and Express

in angularjs at express services I want all the calling services at one place.. something like this structure..
routes(some folder)|-API (all calls)|-Services|-schemas(mongoose)
if these are my services
'use strict';
var express = require('express');
var router = express.Router();
var conveyModel = require('../model/Schema');
console.log("convey api router ready");
/* GET /convey listing. */
router.get('/', function(req, res, next) {
console.log("convey api get '/'");
conveyModel.find(function (err, convey) {
if (err) return next(err);
res.json(convey);
});
});
/* POST /convey */
router.post('/', function(req, res, next) {
console.log("convey api post '/'");
console.log("retrieving:: " + req.body);
conveyModel.create(req.body, function (err, post) {
console.log("saving:: " + post);
if (err) return next(err);
res.json(post);
});
});
module.exports = router
i want to call all services in other Api js somthing like this,
router.post('/api/v1/login', auth.login);
router.get('/api/v1/me', users.getAll);
I'm not able to understand how it works... if there is some working example, with what I want it would be great.
silly me found answer long back but wanan update what i found!!!
in API.js all api calls i gathered like this
var express = require('express');
var router = express.Router();
var fact = require('../services/factRouter');
router.get('/fact', fact.getAll);
router.post('/fact/', fact.create);
module.exports = router;
and in services
'use strict';
var express = require('express');
var router = express.Router();
var factModel = require('../model/factSchema');
var users = {
getAll: function(req, res, next) {
console.log("fact api get '/'");
factModel.find(function (err, fact) {
if (err) return next(err);
res.json(fact);
});
},
create: function(req, res, next) {
console.log("fact api post '/'");
console.log("retrieving:: " + req.body);
factModel.create(req.body, function (err, post) {
console.log("saving:: " + post);
if (err) return next(err);
res.json(post);
});
}
};
module.exports = users;
and obviously in schema
'use strict';
var mongoose = require('mongoose');
var factsSchema = new mongoose.Schema({
title: { type: String },
description: { type: String },
});
module.exports = mongoose.model('facts', factsSchema);
console.log("facts schema defined")
yaaa dat was easy !!!
You can do something like this, in your routes.js can do this:
var express = require('express');
//by right app should have been created beforehand in index.js or app.js
//and just imported here
var app = express();
app.use('/api/users', require('./api/users');
...
then in /api/users create an index.js file with the following content:
var express = require('express');
var router = new express.Router();
var controller = require('./controller');
var auth = require('./service');
router.get('/', auth.isAuthenticated(), controller.getProfile);
module.exports = router;
Put your router controller in ./api/user/controller.js and logic (e.g. database layer or middleware) into ./api/user/service.js.
This is not the only architecture pattern you can use, but it must give you some ideas where to go from here

Why wont this post?

I'm playing around with mongodb + Express and rewriting an old comments app in the latest version of Express.
I've had to change a few things because of the changes in the latest Express. But I'm having some issues.
Basically, it won't post to /create when I submit my form. This is probably a simple fix but any help would be appreciated :)
app.js
require('./models/comments'); // require the model before the 'index.js' file is called
var express = require('express'); var path = require('path'); var favicon = require('static-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser');
var routes = require('./routes/index'); var create = require('./routes/create');
var app = express();
// Database stuff var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/comments-app');
// view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade');
app.use(favicon()); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded()); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes); app.use('/create', create);
/// 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;
Comments.js (model)
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var CommentSchema = new Schema({
username: String,
content: String,
created: Date
});
module.exports = mongoose.model('Comment', CommentSchema);
index.jade
extends layout
block content
h1= title
div.addCommentForm
form( method="post", action="/create")
input(type='text', class='nameTxt', name='username')
div
span.label Comment :
textarea(name='comment')
div#addCommentSubmit
input(type='submit', value='Save')
br
br
#comments
- each comment in comments
div.comment
div.name comment.username
div.created_at= comment.created
br
div.content= comment.content
hr
create.js (route)
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Comment = mongoose.model('Comment', Comment);
router.route('/create')
.post(function(req, res) {
var Comment = new Comment()
username : req.body.username;
content : req.body.comment;
created : Date.now();
Comment.save(function(err) {
if (err)
res.send(err);
res.send('Comment added');
});
});
module.exports = router;
Your jade indenting for the form tag is off. Make sure the input tags you want inside the form tag in the HTML are indented further than the form tag in your jade so they end up as children of the form tag in the HTML.
Oops:
this jade
form
input
yields this HTML
<form></form><input>
Fixed
form
input
yields
<form><input></form>