2

I'm using making error messages available on res.locals and displaying them as needed with a redirect. I am not completely sure how this works, but it does. At least when I'm running the server locally.

Deployed to Heroku on the other hand, it doesn't. There's nothing. I make mistakes on the page and my sexy flash messages are glimmering with their absence.

I'm using sqlite3 locally and storing sessions with connect-session-sequelize.

I'm using postgres on Heroku.

server.js

/* jshint node: true */
'use strict';

var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var _ = require('underscore');
var db = require('./db.js');
var SequelizeStore = require('connect-session-sequelize')(session.Store);
var flash = require('express-flash');
var app = express();
var PORT = process.env.PORT || 3000;

app.use(cookieParser());

// Track logins with express session
app.use(session({
    secret: 'Magic mike',
    resave: true,
    saveUninitialized: false,
    store: new SequelizeStore({
        db: db.sequelize
    })
}));

app.use(flash());

// Make userId available in templates
app.use(function(req, res, next){
    res.locals.currentUser = req.session.userId;
    res.locals.sessionFlash = req.session.sessionFlash;
    delete req.session.sessionFlash;
    next();
});

// To parse incoming req
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));


// Serve static files
app.use(express.static(__dirname + '/public'));

// View engine setup
app.set('view_engine', 'pug');
app.set('views', __dirname + '/views');


var routes = require('./routes/index.js');
app.use('/', routes);
....

db.js

var Sequelize = require('sequelize');
var env = process.env.NODE_ENV || 'development';
var sequelize;

if (env === 'production') {
    sequelize = new Sequelize(process.env.DATABASE_URL, {
        dialect: 'postgres'
    });
} else {
sequelize = new Sequelize(undefined, undefined, undefined, {
    'dialect': 'sqlite',
    'storage': __dirname + '/data/shoplist.sqlite'
});

}

var db = {};

db.item = sequelize.import(__dirname + '/models/item.js');
db.user = sequelize.import(__dirname + '/models/user.js');
// db.shoplist = sequelize.import(__dirname + '/models/shoplist.js');
db.sequelize = sequelize;
db.Sequelize = Sequelize;

// db.item.belongsTo(db.shoplist);
// db.shoplist.hasMany(db.item);
db.item.belongsTo(db.user);
db.user.hasMany(db.item);
// db.user.belongsTo(db.shoplist);
// db.shoplist.hasMany(db.user);


module.exports = db;
....

routes/index.js

var express = require('express');
var router = express.Router();
var _ = require('underscore');
var mid = require('../middleware/');
var db = require('../db.js');
var flash = require('express-flash');

router.all('/login-error', function(req, res) {
    res.redirect(301, '/login');
});

router.all('/register-error', function(req, res) {
    res.redirect(301, '/register');
});

// GET /homepage
router.get('/', function(req, res, next) {
    req.flash('info', 'Velkommen!');
    return res.render('index.pug', {
        title: 'Welcome!',
        url: req.originalUrl
    });
});
....
// POST /login
router.post('/login', function(req, res, next) {
    var body = _.pick(req.body, 'name', 'password');

    if (req.body.name && req.body.password) {
        db.user.authenticate(body).then(function(user) {
            req.session.userId = user.id;
            // To make sure the session is stored in db befor redirect
            req.session.save(function() {
                return res.redirect('makeitem');
            });
        }).catch(function(e) {
            var err = new Error("Wrong username or password.");
            err.status = 400;
            err.message = "Wrong username or password.";
            req.session.sessionFlash = {
                type: 'error',
                message: err.message
            };
            res.redirect('/login-error');

        });
    } else {
        var err = new Error('All fields required.');
        err.status = 400;
        err.message = 'All fields required.';
        req.session.sessionFlash = {
            type: 'error',
            message: err.message
        };
        res.redirect('/login-error');
    }

});
...
// POST /register
router.post('/register', function(req, res, next) {
    var body = _.pick(req.body, 'name', 'email', 'password');

    // Check if all fields are filled out
    if (req.body.name &&
        req.body.email &&
        req.body.password) {

        // // Check that passwords are the same
        if (req.body.password !== req.body.comf_password) {
            var err = new Error('Passwords do not match.');
            err.status = 400;
            err.message = 'Passwords do not match.';
            req.session.sessionFlash = {
                type: 'error',
                message: err.message
            };
            res.redirect('/register-error');
        } else {
            db.user.create(body).then(function(user) {
                //res.json(user.toPublicJSON());
                res.redirect('/login');
            }, function(e) {
                var err = new Error('Email or Shopping List Name in use.');
                err.status = 400;
                err.message = 'There is already a Shopping List with this name or email';
                req.session.sessionFlash = {
                    type: 'error-name',
                    message: err.message
                };
                res.redirect('/register-error');
            });
        }

    } else {
        var err = new Error('All fields required.');
        err.status = 400;
        err.message = 'All fields required.';
        req.session.sessionFlash = {
            type: 'error',
            message: err.message
        };
        res.redirect('/register-error');
    }


});
...

I'm using pug, so this is the way I display messages:

if sessionFlash && sessionFlash.message
            .sessionflash
                p.bg-warning #{ sessionFlash.message }

These are my dependencies:

  "dependencies": {
    "bcrypt": "^0.8.7",
    "body-parser": "^1.15.2",
    "connect-session-sequelize": "^3.1.0",
    "cookie-parser": "^1.4.3",
    "crypto-js": "^3.1.6",
    "express": "^4.14.0",
    "express-flash": "0.0.2",
    "express-session": "^1.14.1",
    "jsonwebtoken": "^7.1.9",
    "pg": "^4.5.6",
    "pg-hstore": "^2.3.2",
    "pug": "^2.0.0-beta6",
    "sequelize": "^3.5.1",
    "sqlite3": "^3.1.4",
    "underscore": "^1.8.3"

Why is this happening? And how do I display flash messages on Heroku?

bguiz
  • 27,371
  • 47
  • 154
  • 243
  • Okay. if i remove `delete req.session.sessionFlash;` from where I make things available on res.locals, the flash message will show on Heroku. But it stays there forever. – Michael Krøyserth-Simsø Oct 01 '16 at 14:51
  • I used express-flash instead and now it works on Heroku. It's identical, only I do this: `eq.flash('error', "Flash " + err.message);` I don't understand why one thing is working and other is not so I would be thankful if anyone could explain it.. Or point me in the direction of relevant knowledge.. – Michael Krøyserth-Simsø Oct 02 '16 at 08:20
  • I'm having the same issue as you did. Looks like I need to switch to express-flash? Or do you know how this works now so I can get it to work with express-session? – ajbraus Jan 02 '19 at 01:22

1 Answers1

-1

Facing the same issue, I realized that it had to do with Cloudflare settings. Forwarding permissions were causing an issue that erased local variables any time I loaded a page. When I simply used the app deploy link with heroku and I stopped having an issue. If you're reading this in the future, use your command line to test the website in production with "NODE_ENV=production npm start" and web with "heroku local web", if both of those are working fine, the problem may be your dns manager.

JSoyinka
  • 1
  • 2
  • 1
    This does not really answer the question. If you have a different question, you can ask it by clicking [Ask Question](https://stackoverflow.com/questions/ask). You can also [add a bounty](https://stackoverflow.com/help/privileges/set-bounties) to draw more attention to this question once you have enough [reputation](https://stackoverflow.com/help/whats-reputation). - [From Review](/review/low-quality-posts/28276985) – bguiz Feb 09 '21 at 05:08
  • @bguiz I edited my answer, but I definitely think it would be better suited as a comment as opposed to an answer, unfortunately I don't have enough reputation to comment. I figured that, either way, it would be helpful for people to know that if they are having a similar problem, it might not be an issue with Heroku. Thoughts on, if that information is worth sharing, and how I'd go about sharing that without being able to leave a comment. – JSoyinka Feb 09 '21 at 06:53