Can't connect to heroku postgres from heroku local using node sample - node.js

I followed the steps at:
https://devcenter.heroku.com/articles/getting-started-with-nodejs#introduction
When I ran heroku local it couldn't connect - I saw that it was using the process.env.DATABASE_URL and got it to my local .env file using:
https://devcenter.heroku.com/articles/heroku-local
But it still wouldn't connect, I've added a console.log to see the error:
"error: no pg_hba.conf entry for host "62.90.xxx.yyy", user "username", database "password", SSL off"
What now?

After a lot of searches it turns out that added 'pg.defaults.ssl = true' solves the problem for me while allowing me to stay as close as possible to the sample provided by Heroku.
Here is my code
const cool = require('cool-ascii-faces');
const express = require('express')
const path = require('path')
const PORT = process.env.PORT || 5000
const pg = require('pg');
pg.defaults.ssl = true; //this is it!!!
express()
.use(express.static(path.join(__dirname, 'public')))
.set('views', path.join(__dirname, 'views'))
....

A neat solution would be enabling SSL only for the Heroku server connection. For that add dialectOptions.ssl=true to Heroku environment in config.json file:
{
"production": {
"use_env_variable": "DATABASE_URL",
"dialectOptions": { "ssl": true },
"logging": false
}

Related

node.js do not work after deploy on Heroku

I am new to node.js and Heroku, I just have deployed for the first time a node.js app to Heroku and when I ran in Heroku, the application did not run so I used the command heroku logs --tail but I had this error:
enter image description here
For idea, my node.js works very fine without Heroku but stop working after deploying it there
Here my index.js:
const express = require("express");
var md5 = require('md5');
var reverseMd5 = require('reverse-md5');
const app = express();
const userRouter = require("./API/users/user.router");
const operationsRouter = require("./API/operations/operations.router");
app.use(express.json());
app.use("", userRouter);
app.use("", operationsRouter);
app.use(express.static('images'));
const port = process.env.APP_PORT || 3000;
app.listen(port, () => {
console.log("server up and running on PORT :", port);
});
Hero my config file java:
const { createPool } = require("mysql");
const pool = createPool({
host: 'host.example.com',
port: 3306,
user: 'user',
password: 'password',
database: 'database',
connectionLimit: 100,
multipleStatements: true
});
module.exports = pool;
What shocked me is that why these errors show up only after deploying on Heroku?
Is there anything I can do to fix this problem?
Heroku dynamically assigns your app a port, so you can't set the port to a fixed number. Heroku adds the port to the env, so you can pull it from there. Switch your APP_PORT listen to this:
.listen(process.env.PORT || 5000)
Make sure you have changed the APP_PORT to PORT.
That way it'll still listen to port 5000 when you test locally, but it will also work on Heroku.
One more thing I can see that you are using Nodemon on Heroku which is not necessary on Heroku. So remove the Nodemon from your Heroku and declare a Procfile
web: node app.js
Being app.js the entry point to your app.

Is there is a way for me to host my express api on the internet?

I have recently started learning MERN stack and I made my first front-end application using React and I connected it using an API that I have created using Express. It works perfectly fine on my local machine using localhost.
But whenever I try to upload it to a hosting service, like Heroku for example, it gives me a 404 error whenever I open the link. Is there is a way for me to upload my API into a hosting service for free or is there is something I'm doing wrong in my code ?
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();
require('dotenv').config({ path: __dirname + '/.env' });
const URI = process.env.URI;
mongoose.connect(URI, { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: true });
const connection = mongoose.connection;
connection.once('once', () => {
console.log('connection to database has been initiated sucessfully');
});
const itemRouter = require('./routes/itemsRouter.js');
const orderRouter = require('./routes/orderRouter.js');
const mailRouter = require('./routes/mailRouter.js');
app.use(express.json());
app.use(cors());
app.use('/items', itemRouter);
app.use('/orders', orderRouter);
app.use('/sendMail', mailRouter);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`App is running on port ${PORT}`);
});
Heroku should work out the box if you've followed the setup here Heroku Dev Center.
However, if you're using freshly shipped ubuntu or similar server. You'll need to set up the environment by doing the following:
Install node run time, nginx & a node deamon manager (In this case PM2)
sudo apt install nodejs nginx
npm install -g pm2
Create an nginx config
server {
listen 80;
index index.html;
server_name YOUR_DOMAIN/SERVER_IP;
location / {
proxy_pass 127.0.0.1:NODE_BOUND_PORT;
}
}
Deamonise the Node script
pm2 start index.js
You'll have to restart nginx and create the symbolic links for NGINX to pick up the routing but once this is done, should route as intended.

heroku DATABASE_URL is undefined in nodejs app

Heroku site states that the DATABASE_URL is setup automatically for you. I used the command
heroku config
to confirm that the DATABASE_URL is indeed set.
However when I use the pg package command
const client = new Client({
connectionString: process.env.DATABASE_URL,
ssl: true,
});
and do a console.log(process.env.DATABASE_URL), the variable reads as undefined.
The other errors that I am getting are:
UnhandledPromiseRejectionWarning: Error: The server does not support SSL connections
The complete code is:
const express = require('express');
require('dotenv').config();
const { Client } = require('pg');
const app = express();
console.log(process.env.DATABASE_URL);
const client = new Client({
connectionString: process.env.DATABASE_URL,
ssl: true,
});
client.connect();
client.query('SELECT * FROM customers;', (err, res) => {
if (err) throw err;
for (let row of res.rows) {
console.log(JSON.stringify(row));
}
client.end();
});
app.get('/', (req, res) => {
res.send('Hello World')
});
app.listen(4000, () => {
console.log(`Server started on port`);
});
The code works when I use my local postgresql database, but when I try to connect to Heroku's postgres database, the above errors occur. Any suggestions?
Seems you're not crazy... This isn't working for me either, so I dug in, and it just seems... broken.
https://stackoverflow.com/a/19341505/4526479
I see DATABASE_URL defined in the heroku config vars section in the online heroku dashboard. But it's just undefined in the app.
It looks like you're running into issues connecting to the Heroku Postgres database when you run the project locally.
The DATABASE_URL environment variable specified in heroku config exists only on the Heroku server and you don't have the environment variable set locally.
Create a .env file and include your connection string like so
DATABASE_URL=...
Here you can include the connection string for the database hosted on Heroku, or your local Postgres database server. Just make sure SSL is configured correctly

Mongodb atlas + node.js working locally but stop when pushed to Heroku

I created a post route in my node.js website that allows users to apply for a job. It was working great locally and connecting to mongodb atlas but when I pushed the app to Heroku and try to submit the form for the job application my website times out. I am fairly new at this and do not know what to do. Thanks
Here is my code
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var Applicant = require('./models/applicants');
var sendAppliedEmail = require('./mail/index.js');
var app = express();
app.set('view engine', 'ejs');
app.use(express.static(__dirname + "/public"));
app.use(express.static(__dirname + '/js'));
var port = process.env.PORT || 3000;
mongoose.connect('mongodb+srv://klaurtar:************#cluster0-nakj7.mongodb.net/test?retryWrites=true', {useNewUrlParser: true});
app.use(bodyParser.urlencoded({extended: true}));
here is my terminal when i run heroku logs
I see that MongoNetworkError is occurring, and if the things are working fine at local but not at Heroku, then IP whitelisting might be the issue. IP need to be whitelisted at MongoDB Atlas before we go for making any connection. In case you don't know the IP (heroku), you can put it as 0.0.0.0/0
I faced similar issue in past and this worked for me.
I faced the same problem when i tried to move from mlab to Atlas MangoDb. So the solution I found was to add config vars in your Heroku application.
Go to you Heroku application click on Settings
Click on Reveal Config Vars
add a new KEY: MONGODB_URL
add a new VALUE: YOUR CONNECTION STRING
refresh your Heruko application and you are good to go.
PS: Make sure your dbconnection is working. In case of questions i gonna left my connection to compare:
mongoCFG = {
useNewUrlParser: true,
ssl: true,
replicaSet: '<clusterName>-shard-0',
authSource: 'admin',
retryWrites: true,
useUnifiedTopology: true,
}
console.log('Attempting to connect to mongoose');
mongoose.connect(config.mongoURL, mongoCFG)
.then(() => {
console.log("Connected to Mongo database!");
})
.catch(err => {
console.error("App starting error:", err.stack);
});```
I whitelisted my IP with mongodb atlas and updated my code to save the uri as a variable and it now works in Heroku production. Here is my code that ended up working.
var uri = "mongodb+srv://klaurtar:************#cluster0-nakj7.mongodb.net/test?
retryWrites=true";
mongoose.connect(uri, {useNewUrlParser: true});
var db = mongoose.connection;
Is your MongoDB running on GCP or Azure? If so, they require an IP Whitelist of 0.0.0.0/0 and then Restart All Dynos on your Heroku browser console (it is located in the top right More dropdown).
These articles were helpful:
https://docs.atlas.mongodb.com/security-whitelist/
.17 on: https://cloud.google.com/community/tutorials/mongodb-atlas-appengineflex-nodejs-app

Deploying nodejs/mongoose to heroku

This is my first try at Heroku. I was able to "deploy successful" on heroku, but when visiting my app, it says "application failed."
I followed this guide:
https://scotch.io/tutorials/use-mongodb-with-a-node-application-on-heroku
I think the tricky thing is because I'm using Mongoose, it may not relate well with the URI. I'm also using mlab addon.
Here's my setup for my backend:
var request = require('request');
var app = express();
var mongoCredentialss = require('/mongo_credentialss.json');
var conn = mongoose.connection;
var path = require('path');
// connect to the database
mongoose.connect('mongodb://' + mongoCredentials.username + ':' + mongoCredentialss.password + '#ds012345.mlab.com:12345/mydatabase-db');
mongoose.Promise = Promise;
app.listen(3000, function() {
console.log('Listening on 3000...');
});
I didn't really understand the .env, to make it work locally, I just stored my username and password in a hidden .json file thanks to .gitignore. From the guide though, I just tried embedding URI straight into my node file as a variable to see if that even works. I'm not too sure how 'hidden environments' work...
Later on when I started over, I also kept having a recurring problem with heroku not detecting its standard buildpacks:set heroku/nodejs
****EDIT:
Still seeing some issues. I took out my 'mongo creds' so my server.js file now looks like this:
var express = require('express');
var mongoose = require('mongoose');
mongoose.connect(process.env.MONGODB_URI);
var Promise = require('bluebird');
var bodyParser = require('body-parser');
var randtoken = require('rand-token');
var cors = require('cors');
var request = require('request');
var app = express();
var conn = mongoose.connection;
var fs = require('fs');
var path = require('path');
app.listen(3000, function() {
console.log('Our app is running on http://localhost:' + 3000);
});
Some further context: I have one main project folder, which houses 2 sub folders: backend and frontend. When I deploy it to heroku, I change directory into the main folder to deploy everything.
Also, if it helps, here's what my package.json looks like:
"dependencies": {
"bluebird": "^3.4.1",
"body-parser": "^1.15.2",
"cors": "^2.7.1",
"express": "^4.14.0",
"mongoose": "^4.5.3",
"my-bcrypt": "^1.0.2",
"rand-token": "^0.2.1",
"request": "^2.74.0"
},
"engines": {
"node": "==6.0.0"
}
}
******EDIT 2:
heroku logs can't find my 'backend.js'. Right now, I've got one main project folder directory, inside it is 2 folders: --->backend.js (node) and --->frontend.js (angular)
My package.json looks like this:
**"main": "frontend.js",**
"scripts": {
**"start": "node backend.js",**
"test": "echo \"Error: no test specified\" && exit 1"
},
I may be misunderstanding how heroku is finding my main .js files. From my understanding 'start' is for the node file, and the 'main' file is for the frontend stuff like angular/html stuff.
You should be able to connect Mongoose to your MLab database by doing this:
mongoose.connect(process.env.MONGODB_URI);
When you are using an addon on Heroku, the provider (MLab in this case) will create a database for you, and then store the connection details (the URL with the database host, username, password, port, etc.) as an environment variable that your application can use.
That's why you need to pass that environment variable process.env.MONGODB_URI into mongoose.connect: it will connect you to the right database =)
UPDATE: Since you updated your question, I noticed another issue that will prevent this from running. You need to tell your app to listen on a specific Heroku port (not 3000).
What you should do is modify your app.listen(3000) call to instead say: app.listen(process.env.PORT || 3000); This will force your application run correctly on both Heroku AND you local development box.
You require mongo using this line:
var mongoCredentialss = require('/mongo_credentialss.json');
but you've set your password in your mongoCredentials as:
mongoose.connect('mongodb://' + mongoCredentials.username + ':' + mongoCredentialss.password + '#ds012345.mlab.com:12345/mydatabase-db');
your username is bound to mongoCredentials.username rather than the mongoCredentialss.username
Simple typo in the code which is bound to lead to db connection errors.

Resources