Knex Postgres Heroku - Error: Unable to Acquire Connection - postgresql

I'm aware of the post and similar question here(Knex Migration Postgres Heroku - Error: Unable to Acquire Connection) I'm not sure what is missing in my .env I just basically have the following line in there : HOST= http://localhost:3000.
My knexfile:
module.exports = {
development: {
client: 'pg',
connection: 'postgres://localhost/eka_dev',
migrations: {
tableName: 'knex_migrations'
}
},
test: {
client: 'pg',
connection: 'postgres://localhost/eka_test',
migrations: {
tableName: 'knex_migrations'
}
},
production: {
client: 'pg',
connection: process.env.DATABASE_URL,
migrations: {
tableName: 'knex_migrations'
}
}
};
Knex file:
const environment = process.env.NODE_ENV || 'development';
const knexConfig = require('./knexfile')[environment];
const knex = require('knex')(knexConfig);
module.exports = knex;
app.js file:
const express= require('express');
const PORT = process.env.PORT || 3000;
const app = express();
const bodyParser = require('body-parser');
const path = require('path');
const cors = require('cors');
const usersRoute = require('./routes/users');
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config();
}
const allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
if (req.method == 'OPTIONS') {
res.send(200);
} else {
next();
}
};
app.use(allowCrossDomain);
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'build')));
app.use('/api', usersRoute);
app.listen(PORT, () => {
console.log(`Express server listening on port ${PORT}`);
});
module.exports = app;

You need to define NODE_ENV=production environment variable in your Heroku setup and check what is the contents of DATABASE_URLvariable.

Related

How can I config my database connection on TypeORM?

I used to use this config, but connect and getConnectionManager are deprecated.
import { getConnectionManager } from "typeorm";
if (process.env.NODE_ENV === 'production' && process.env.DATABASE_URL.indexOf("sslmode=require") === -1) {
process.env.DATABASE_URL += "?sslmode=require";
}
export default async function connect () {
const connectionManager = await getConnectionManager();
const connection = connectionManager.create({
name: "default",
type: "postgres",
url: process.env.DATABASE_URL,
entities: [`${process.env.NODE_ENV === 'production' ? 'dist' : 'src'}/entities/*.*`],
ssl: process.env.NODE_ENV === 'production'
});
await connection.connect();
return connection;
}
I have tried to use this config, but when I try to made a request receive the error: DataSource is not set for this entity.
import { DataSource } from "typeorm";
if (process.env.NODE_ENV === 'production' && process.env.DATABASE_URL.indexOf("sslmode=require") === -1) {
process.env.DATABASE_URL += "?sslmode=require";
}
export default async function connect () {
const dataSource = new DataSource({
name: "default",
type: "postgres",
url: process.env.DATABASE_URL,
entities: [`${process.env.NODE_ENV === 'production' ? 'dist' : 'src'}/entities/*.*`],
ssl: process.env.NODE_ENV === 'production'
});
const connection = await dataSource.initialize();
return connection;
}

Express-session does not create any session

Im trying to implement some basic sessions functionality in my toy project with express-session and connect-mongo for session storage.
What i expect:
Browser gets cookie after recieving response from server
Session data is written to collection "sessions"
I get debug messages from express-session in console, because i start the app with DEBUG=express-session:* nodemon ./bin/www
What i get instead:
Browser never gets cookie
No documents are being created in the collection (the collection itself is being created every time i launch the app though)
There are no debug messages from express-session in the console
Everything related to DB and session setups in the app.js file:
// DB setup
var mongoDB = require('./k'); // K is a file containing connection string
mongoose.connect(mongoDB, {
useNewUrlParser: true,
useUnifiedTopology: true
})
var db = mongoose.connection
db.on('error', console.error.bind(console, 'MongoDB connection Error: '))
// Session setup
const connection = mongoose.createConnection(mongoDB, {
useNewUrlParser: true,
useUnifiedTopology: true
})
const sessionStore = new MongoStore({
mongooseConnection: connection,
collection: 'sessions'
})
app.use(session({
secret: 'some secret',
resave: false,
saveUninitialized: true,
store: sessionStore,
cookie: {
maxAge: 1000 * 60 * 60 * 24
}
}));
Is there anything i clould be missing? What could be causing this issue for me?
Try:
var MongoStore = require('connect-mongostore')(session);
app.use(session({
secret: 'my secret',
store: new MongoStore({'db': 'sessions'})
}));
Looks like the problem was being caused by the order of middleware in my app.js file. I moved the code with DB setup and session setup right above routers and it worked. app.js before:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var entriesRouter = require('./routes/entries')
const categoriesRouter = require('./routes/categories')
const session = require('express-session');
const MongoStore = require('connect-mongo')(session)
const mongoose = require('mongoose')
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({
extended: false
}));
// app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/entries', entriesRouter)
app.use('/categories', categoriesRouter)
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// 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');
});
// DB setup
var mongoDB = require('./k'); // K is a file containing connection string
mongoose.connect(mongoDB, {
useNewUrlParser: true,
useUnifiedTopology: true
})
var db = mongoose.connection
db.on('error', console.error.bind(console, 'MongoDB connection Error: '))
// Session setup
const connection = mongoose.createConnection(mongoDB, {
useNewUrlParser: true,
useUnifiedTopology: true
})
const sessionStore = new MongoStore({
mongooseConnection: connection,
collection: 'sessions'
})
app.use(session({
secret: 'some secret',
resave: false,
saveUninitialized: true,
store: sessionStore,
cookie: {
maxAge: 1000 * 60 * 60 * 24,
secure: false
}
}));
module.exports = app;
app.js after:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var entriesRouter = require('./routes/entries')
const categoriesRouter = require('./routes/categories')
const session = require('express-session');
const MongoStore = require('connect-mongo')(session)
const mongoose = require('mongoose')
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({
extended: false
}));
// app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// DB setup
var mongoDB = require('./k'); // K is a file containing connection string
mongoose.connect(mongoDB, {
useNewUrlParser: true,
useUnifiedTopology: true
})
var db = mongoose.connection
db.on('error', console.error.bind(console, 'MongoDB connection Error: '))
// Session setup
const connection = mongoose.createConnection(mongoDB, {
useNewUrlParser: true,
useUnifiedTopology: true
})
const sessionStore = new MongoStore({
mongooseConnection: connection,
collection: 'sessions'
})
app.use(session({
secret: 'some secret',
resave: false,
saveUninitialized: true,
store: sessionStore,
cookie: {
maxAge: 1000 * 60 * 60 * 24,
secure: false
}
}));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/entries', entriesRouter)
app.use('/categories', categoriesRouter)
// catch 404 and forward to error handler
app.use(function (req, res, next) {
next(createError(404));
});
// 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;

Heroku: My routes still pointing to localhost when deployed

I set up my NODE_ENV to production under APP>Settings>Config Vars on Heroku and set up a mongo.json file in my root directory:
{
"development": {
"host": "127.0.0.1:27017",
"dbName": "hillfinder"
},
"production": {
"PRODUCTION_DB_DSN": "mongodb+srv://***credentials***#hillfinder-qjxuo.mongodb.net/production?retryWrites=true&w=majority"
}
}
But it's still pointing to localhost:
This is the my server/index.js:
const express = require('express');
require('dotenv').config();
const nextJS = require('next');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var bodyParser = require('body-parser');
var auth = require('./lib/auth');
var cors = require('cors');
var morgan = require('morgan');
var HttpStatus = require('http-status-codes');
var PORT = process.env.PORT || 8016;
const { isBlockedPage, isInternalUrl } = require('next-server/dist/server/utils');
function NODE_ENVSetter(ENV) {
var environment,
environments = {
production: () => {
environment = process.env.PRODUCTION_DB_DSN;
console.log(`We are currently in the production environment: ${environment}`);
return environment;
},
test: () => {
environment = process.env.TEST_DB_DSN;
console.log(`We are currently in the test environment: ${environment}`);
return environment;
},
default: () => {
environment = process.env.DEVELOPMENT_DB_DSN;
console.log(`We are currently in the development environment: ${environment}`);
return environment;
}
};
(environments[ENV] || environments['default'])();
return environment;
}
var db = NODE_ENVSetter('production');
var mongoose = require('mongoose');
function errorHandler(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 : {};
// Log error
console.error(err.stack);
// Render the error page
res.status(err.status || 500);
// Default error message by HTTP code
res.render('error', {
title: HttpStatus.getStatusText(err.status),
message: HttpStatus.getStatusText(err.status)
});
}
async function start() {
const dev = process.env.NODE_ENV !== 'production';
const app = nextJS({ dev });
const server = express();
await app
.prepare()
.then(() => {
mongoose.connect(db, { useNewUrlParser: true });
mongoose.Promise = global.Promise;
mongoose.connection
.on('connected', () => {
console.log(`Mongoose connection open on ${db}`);
})
.on('error', err => {
console.log(`Connection error: ${err.message}`);
});
})
.catch(err => {
console.error(err);
});
server.set('view engine', 'html');
server.use('/uploads', express.static(__dirname + '/uploads'));
server.use(bodyParser.urlencoded({ limit: '50mb', extended: false }));
server.use(bodyParser.json({ limit: '50mb' }));
server.use(morgan('dev'));
server.use(cookieParser());
server.use(
session({
secret: 'very secret 12345',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
})
);
server.use(auth.initialize);
server.use(auth.session);
server.use(auth.setUser);
console.log('auth.setUser ', auth.setUser);
server.use(cors());
server.use('/users', require('./users'));
server.use('/images', require('./images'));
// Redirect all requests to main entrypoint pages/index.js
server.get('/*', async (req, res, next) => {
try {
const pathName = req.originalUrl;
if (isInternalUrl(req.url)) {
return app.handleRequest(req, res, req.originalUrl);
}
if (isBlockedPage(pathName)) {
return app.render404(req, res, req.originalUrl);
}
req.locals = {};
req.locals.context = {};
const html = await app.renderToHTML(req, res, '/', {});
// Handle client redirects
const context = req.locals.context;
if (context.url) {
return res.redirect(context.url);
}
// Handle client response statuses
if (context.status) {
return res.status(context.status).send();
}
// Request was ended by the user
if (html === null) {
return;
}
app.sendHTML(req, res, html);
} catch (e) {
next(e);
}
});
// error handler
server.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.errorStatus = err.status;
res.locals.errorMessage = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
console.log('err.status ', err.status);
res.status(err.status).send(err.message);
});
server.listen(PORT, err => {
if (err) throw err;
console.log(`> Ready and listening on http://localhost:${PORT}`);
});
}
start();
How would I fix that so I can log on to MongoDB atlas?
Thank you in advance!

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 connect to MongoDb with Hapi.js?

Does anyone know how to connect to MongoDb while using the Hapi.js framework?
I have only managed to find one example (https://github.com/Marsup/hapi-mongodb), but this requires using a plugin and has no comments in the code!
Does anyone know of a simpler way?
The following (using mongoose) works pretty well for me:
var Hapi = require('hapi');
var mongoose = require("mongoose");
var server = new Hapi.Server();
server.connection({ port: 3000 });
var dbUrl = 'mongodb://localhost:27017/mydb';
var dbOtions = {
db: { native_parser: true },
server: { poolSize: 5 }
};
server.register([ /* plugins */], function (err) {
if (err) {
throw err; // something bad happened loading the plugins
}
// ... Register the routes
server.start(function () {
mongoose.connect(dbUrl, dbOtions, function(err) {
if (err) server.log('error', err);
});
});
});
I use a hapi plugin that I wrote that connects to mongo, handles errors to log and adds bluebird promises.
'use strict';
var bluebird = require('bluebird');
var mongoose = bluebird.promisifyAll(require('mongoose'));
exports.register = function(plugin, options, next) {
mongoose.connect(options.mongo.uri, options.mongo.options, function (e) {
if (e) {
plugin.log(['error', 'database', 'mongodb'], 'Unable to connect to MongoDB: ' + e.message);
process.exit();
}
mongoose.connection.once('open', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('connected', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('error', function (e) {
plugin.log(['error', 'database', 'mongodb'], 'MongoDB ' + e.message);
});
mongoose.connection.on('disconnected', function () {
plugin.log(['warn', 'database', 'mongodb'], 'MongoDB was disconnected');
});
});
return next();
};
exports.register.attributes = {
name: 'mongoose',
version: '1.0.0'
};
Blog post on user authentication with passport and Mongoose
Also be aware that Hapi's model is based off of plugins so read and re-read the docs on building your own.
Visit http://cronj.com/blog/hapi-mongoose
Complete sample project which can help you Repo Link https://github.com/gauravgupta90/Hapi-Mongoose-Angular
Config.js
module.exports = {
server: {
host: '0.0.0.0',
port: 8000
},
database: {
host: '127.0.0.1',
port: 27017,
db: 'DatabaseName',
username: '',
password: ''
}
};
Server.js
var Hapi = require('hapi'),
Routes = require('./routes'),
config = require('./config'),
Db = require('./database');
var server = Hapi.createServer(config.server.host, config.server.port, {
cors: true
});
server.route(Routes.endpoints);
server.start(function() {
console.log('Server started ', server.info.uri);
});
Database.js
var Mongoose = require('mongoose'),
config = require('./config');
Mongoose.connect('mongodb://' + config.database.host + '/' + config.database.db);
var db = Mongoose.connection;
db.on('error', console.error.bind(console, 'connection error'));
db.once('open', function callback() {
console.log("Connection with database succeeded.");
});
exports.Mongoose = Mongoose;
exports.db = db;
The following works for me:
const Hapi = require("hapi");
const Mongoose = require("mongoose");
const server = new Hapi.Server({ "host": "localhost", "port": 3000 });
Mongoose.connect('mongodb://localhost:27017/testdb', { useNewUrlParser: true }, (err) => {
if (!err) { console.log('MongoDB Connection Succeeded.') }
else { console.log(`Error in DB connection : ${err}`)}
});