I developed a Node.js RestAPI to communicate with a MongoDB database. While I was developing using localhost everything worked fine, but now I need to deploy it to a server so users can test it.
The server is running Ubuntu 16.04, and I have successfully installed the software I need (Node.js and MongoDB) and I'm able to start the server, however, I can't make any request using the client.
If I ping the server I'm able to get a response. I have my Node.js RestAPI running on port 4000.
Any idea what I might be doing wrong or what I might have forgotten? This is the first time I'm deploying to a server.
My server.js file is:
const port = 4000
const bodyParser = require('body-parser')
const express = require('express')
const jwt = require('jsonwebtoken')
const cors = require("cors")
const mongoose = require('mongoose')
const databaseConfig = require('./database')
const server = express()
server.use(cors())
server.options('*', cors());
server.use(bodyParser.urlencoded({ extended: true }))
server.use(bodyParser.json())
server.set('superSecret', databaseConfig.secret)
server.listen(process.env.port || port, function () {
console.log('Listening')
})
mongoose.connect(databaseConfig.database, function(err, db) {
if (err) {
console.log('Unable to connect to the server. Please start the server. Error:', err);
} else {
console.log('Connected to Server successfully!');
}
});
module.exports = server
Any help is appreciated. Thank you.
To stop anyone from wasting time on this topic turns out the employee at my university that was supposed to make the host machine IP public forgot to do it! That was the problem, nothing else.
Related
I trying to open a local website on my local network that I can access from every devices in my network.
I use React as frontend, Nodejs as backend and mongodb is my database(Locally).
On the computer where everything is running I can enter the site through my address on the local network and see the data that is in the database, but as soon as I enter the site through another computer that is on the same network I see the site but not the data from the database.
How i can fix this ?
I use this code for the node js server and run node server in terminal:
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const ip = require('ip');
const app = express();
require('dotenv').config();
app.use(cors());
app.use(express.json());
const uri = process.env.ATLAS_URI;
mongoose.connect(uri);
const connection = mongoose.connection;
connection.once('open', () => {
console.log('MongoDB database connection established successfully');
});
const exercisesRouter = require('./routes/exercises');
const usersRouter = require('./routes/users');
app.use('/exercises', exercisesRouter);
app.use('/users', usersRouter);
app.use(express.static('../build'));
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve('../build/index.html'));
});
const PORT = process.env.PORT || 3000;
console.log('server started on port:', PORT, ip.address());
app.listen(PORT,"0.0.0.0");
First thing is to specify the react HOST. If you're using create-react-app, Simply run HOST=your_ip npm run start.
To get this your_ip, run ifconfig on unix systems, and you'll find the IP for the your PC on the LAN you're connected to.
For the nodejs side, you might need to try something like
server.listen(80, 'current_local_ip');.
I am new to fullstack development and I want to deploy a project that will be used on the same network by different users. I have used angular for the front-end and node/express and MySQL for the backend. Before proper deployment, for testing purposes, I am accessing my application from another computer that is on the same network. The application, however, is throwing an error when I try to login.
VM12:1 POST http://localhost:3000/auth net::ERR_CONNECTION_REFUSED
Here's my backend code:
server.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mysqlConnection = require('./connection');
const routes = require('./routes');
const http = require('http');
const path = require('path');
var app = express();
app.disable('x-powered-by');
app.use(express.static(__dirname + '/dist'));
app.get('/*', (req, res) => res.sendFile(path.join(__dirname)));
app.use(cors());
app.use(bodyParser.json());
app.use(routes);
const port = process.env.PORT || 3000;
const server = http.createServer(app);
server.listen(port, '0.0.0.0', () => console.log(`Running on port ${port}`));
routes.js
router.post("/auth", (req, res) => {
var email = req.body.email;
var password = req.body.password;
var accessBasic = "Basic";
var accessPremium = "Premium";
mysqlConnection.query("SELECT * FROM authorization WHERE email = ? AND password = ?", [email,
password], (err, results) => {
if(!err)
{
var myJSON = JSON.stringify(results);
var check_email = myJSON.search(/email/i);
var check_password = myJSON.search(password);
var check_access = myJSON.search(accessBasic);
var check_access2 = myJSON.search(accessPremium);
if ((check_email != -1) && (check_password != -1) && (check_access != -1))
{
res.send("Successfully Authorized to Basic Access");
}
else if ((check_email != -1) && (check_password != -1) && (check_access2 != -1))
{
res.send("Successfully Authorized to Premium Access");
}
else
{
res.send("Authorization failed");
}
}
else
{
console.log("Connection to authorization failed: " + err.message);
}
})
})
I have allowed incoming connections in my firewall and done everything but, couldn't find the reason why my endpoint is refusing to connect while trying to connect on device other than my system on the same network. I don't know what's wrong. Anybody has any idea what am I doing wrong? I have hosted my application on my system and accessing it from another on the same network.
EDIT: Since, this question has gained quite a lot of views, I would like to mention that I didn't change any of the firewall settings as mentioned above. All the default firewall settings of the Windows OS were used. I just deployed the app and ran it.
ANSWER: I was having an issue on the front-end. I was targeting localhost instead of the IP address of the system that the app was hosted on. See my answer below for the details.
For anyone who is going to see this in future. I was having an error on my front-end. Instead of calling http://localhost:3000/name-of-my-api-endpoint, I changed the localhost to the IP address of my system and then ran ng build --prod again in order to make new static files and serve them from node.js.
I have experienced the same issue with MongoDB
I have found out that the problem was my MongoDB wasn't connected to my localhost and the issue was related to tokens and authentication.
So I went to my terminal on my backend folder and ran the command -
npm install dotenv --save
Then I created my .env file located in my backend folder
and added the following commands
PORT=3000 APP_SECRET="RANDOM_TOKEN_SECRET"
MONGODB="mongodb+srv://youruser:yourpassword#cluster0.k06bdwd.mongodb.net/?retryWrites=true&w=majority"
Then called it in my app.js file
const dotenv = require("dotenv");
dotenv.config();
mongoose.connect(process.env.MONGODB,
{ useNewUrlParser: true,
useUnifiedTopology: true })
.then(() => console.log('Connected to MongoDB!'))
.catch(() => console.log('Failed to connect to MongoDB !'));
module.exports = app;
Finally I have added it in my backend/controllers/user.js
const token = jwt.sign(
{userId: user._id},
process.env.APP_SECRET,
{expiresIn: '24h'});
res.status(200).json({
userId: user._id,
token: token
});
You can access your app in the same network from your #IP not from localhost (127.0.0.1) change it to 192.168.1.X (your local #IP address) and make sure to changed it in your .env file.
I've managed to get my Node.js app working properly with my Heroku Postgres database when the node application is deployed to Heroku. However having to deploy to heroku each time I make a code change is a bit arduous and I'd rather be able to develop locally and connect to the database from my local app.
https://devcenter.heroku.com/articles/connecting-to-heroku-postgres-databases-from-outside-of-heroku
The above article doesn't really describe how this is done, I'm not exactly sure what I need to do.
If I attempt to run my app locally and access an endpoint that queries my database I get
Error Error: connect ECONNREFUSED 127.0.0.1:5432
Whereas if I access the same endpoint from my heroku deployed app it works correctly.
Here's my app
const express = require('express')
const path = require('path')
const PORT = process.env.PORT || 5000;
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
});
express()
.use(express.static(path.join(__dirname, 'public')))
.set('views', path.join(__dirname, 'views'))
.set('view engine', 'ejs')
.get('/', (req, res) => res.render('pages/index'))
.get('/users', async (req, res) => {
try {
const client = await pool.connect();
const result = await client.query('SELECT * FROM users');
const results = { 'results': (result) ? result.rows : null};
console.log(results);
res.status(200).json(results);
} catch (err) {
console.error(err);
res.send("Error " + err);
}
})
.listen(PORT, () => console.log(`Listening on ${ PORT }`));
I think you need to update the the process.env.DATABASE_URL on your local machine. From the error, it looks like the DATABASE_URL refers to localhost while you want to use the db hosted on Heroku.
I understand that you only want to use the remote db only. The error says you're unable to connect to 127.0.0.1:5432. This is the IP address of localhost, not the remote database. Your code is trying to connect to 127.0.0.1:5432 for some reason while it should be trying to connect to the remote db.
Did you use the dotenv to access process.env.DATABASE_URL ?
You need dotenv.config(); worked for me.
I have a node.js server that has HTTP CRUD functions to my mongoDB.
And an Android application that sends requests though those functions.
I would like to ensure that my server will answer requests from specific origins.
For example: only answer requests from the android app, or my pc postman's requests.
How can I ensure that no one else sending requests using the same urls and ports will get answered?
This is my server.js file:
const express = require('express');
const MongoClient = require('mongodb');
const bodyParser = require('body-parser');
var db = require('./config/db');
var app = express();
const port = 8000;
app.use(bodyParser.json());
MongoClient.connect(db.url, (err, database) => {
if (err) return console.log(err)
db = database.db("getremp")
require('./app/routes')(app, db);
app.listen(process.env.PORT || port, () => {
console.log("Express server listening on port %d in %s mode - We Are lIVE!",app.settings.env.port, app.settings.env);
});
})
and my index.js:
const noteRoutes = require('./note_routes');
module.exports = function (app, db) {
noteRoutes(app, db);
};
You can control this with :
Send a specific header with your datas containing a secret key, then control the header in your node app How to check headers in nodejs?
Use HMAC in order to authenticate the user and control the integrity of datas : Node Hmac Authentication
But you've to remember that all traffic going out from an mobile app can be intercept (with Fiddler for example). Never use a static (non-dynamic) value to ensure authentication
I've got an AWS EC2 MEAN instance up and running (partially). The app is a RESTful JSON service and as far as I can tell is up and running as expected:
var app = require('./app');
var port = process.env.PORT || 3000;
var server = app.listen(port, function() {
console.log('Express server listening on port ' + port);
});
console output:
node server.js
Express server listening on port 3000
Db.prototype.authenticate method will no longer be available in the
next major release 3.x as MongoDB 3.6 will only allow auth against
users in the admin db and will no longer allow multiple credentials on
a socket. Please authenticate using MongoClient.connect with auth
credentials.
I've also added the Inbound Security Group for port 3000
testing the API out in the browser is where I run into problems... If I attempt to GET a list of objects using http://ec2-XX-XX-XX-XX.com:3000/belts the call eventually times out. However when I try a GET for a single object using http://ec2-XX-XX-XX-XX.com:3000/belts/some_id_here I get a valid 200 response with the expected object.
Of course everything works as expected locally. What am I missing?
Thanks in advance
//edit with requested code formatted :)
//app.js
var express = require('express');
var app = express();
var BeltController = require('./controller/BeltController');
app.use('/belts', BeltController);
//Belt Controller
router.get('/', function (req, res) {
Belt.find({}, function (err, belts) {
if (err) {
return res.status(500).send("There was a problem finding the Belt. " + err);
}
res.status(200).send(belts);
});
});