Deploy Node.js socket.io project on shared OVH server - javascript

I'm trying to build and deploy my app to OVH server, my client doesn't want a cloud solution, he want to host it or deploy it on OVH (they told me OVH support Node.js) and to be honest i have no idea how to do it.
my project work fine in development, its a Real-time chat with socket.io and MySql and some package as knex, in front-end i worked with React.js ( which i have no problem with it right now )
I can provide more informations if needed. thx a lot
const app = require("express")();
var cors = require("cors");
app.use(cors());
const server = require("http").createServer(app);
const mysql = require("mysql");
const knex = require("knex")({
client: "mysql",
connection: {
host: "localhost",
user: "root",
password: "",
database: "chat_message",
},
});
const io = require("socket.io")(server, {
cors: {
origin: "*",
credentials: true,
},
});
app.get("/messages", function (request, result) {
knex
.select()
.table("messages")
.then((data) => result.send(data))
});
io.on("connection", (socket) => {
socket.on("messageClient", (sms) => {
knex("messages")
.insert({
message: sms.msg,
socket_id: sms.id,
dateMsg: sms.Temps,
ip: sms.ip,
name: sms.name,
})
.then((e) => console.log("data insert succees"));
socket.broadcast.emit("messageAll", sms);
});
});
server.listen(5000, () => console.log("Port: 5000"));

OVH is a private company and I'm not sure if this would be offtopic and more suitable to ask their own support. However you should know that shared hosting in general does not support long running processes like nodejs. They only support PHP on the server.

Related

Getting nodeJS web server to send form data to my email

I am trying to get the data my nodeJS server is receiving from a form on the front end to send that data to my email. I have tried to use nodemailer and haven't succeeded much. Can someone tell me perhaps what I am doing wrong with the following code?
const express = require("express");
const app = express();
const nodemailer = require("nodemailer");
var smtpTransport = require("nodemailer-smtp-transport");
const PORT = process.env.PORT || 4000;
app.use(express.static(__dirname + "/front-end"));
app.get("/", (req, resp) => {
resp.sendFile(__dirname + "/front-end/index.html");
});
app.use(express.json());
app.use(express.urlencoded());
app.post("/formData", (req, resp) => {
const data = req.body;
var transport = nodemailer.createTransport(
smtpTransport({
service: "Gmail",
auth: {
user: "user#gmail.com",
pass: "123456",
},
})
);
transport.sendMail(
{
//email options
from: "Sender Name <email#gmail.com>",
to: "Receiver Name <receiver#email.com>", // receiver
subject: "Emailing with nodemailer", // subject
html: data, // body (var data which we've declared)
},
function (error, response) {
//callback
if (error) {
console.log(error);
} else {
console.log("Message sent:");
resp.send("success!");
}
transport.close();
}
);
});
app.listen(PORT, () => {
console.log(`server running on port ${PORT}`);
});
Your code, at a glance, looks fine to me. I think the problem is (since you’re not stating you have set that up), that you want to send email with GMail. If you want to send email from your own app or web service via Gmail, you should set up a project in the Google Cloud Platform. Read more here.
Alternatively, you could use a service like Postmark, which you can configure to send emails via a domain that you own. There’s a free trial. Mailgun is a similar service. (I’m not affiliated to either).

External database connection passing authentication errors on Heroku app

I've been having a strange issue where I've created a basic Nodejs API that I'm trying to host on Heroku which works perfectly from a local standpoint but as soon as I try to test through Heroku I get an authentication error when a MySQL connection is attempted.
From what I can see, when doing Postman tests, Heroku is adding information to my connection information which then causes authentication failure. Authentication to the API itself works but fails the MySQL connection.
const express = require('express');
const mysql = require('mysql');
const cors = require('cors');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const utils = require('./utils');
const app = express();
const leadsdb = mysql.createPool({
host: "hostIP",
user: "username",
password: "password",
database: "database",
});
const port = process.env.PORT || 4000;
// enable CORS
app.use(cors());
// parse application/json
app.use(bodyParser.json());
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
app.post("/api/register", (req, res) => {
const firstName = req.body.firstName
const lastName = req.body.lastName
const email = req.body.email
const number = req.body.number
const country = req.body.country
const age = req.body.age
const occupation = req.body.occupation
const sqlInsert = "INSERT INTO Leads (FirstName, LastName, Email, Country, Phone, Age, Occupation) VALUES (?,?,?,?,?,?,?)"
leadsdb.query(sqlInsert, [firstName, lastName, email, country, number, age, occupation], (err, result) => {
if(!result) {
res.send(err)
}
else {
res.send(result)
}
})
{
"code": "ER_ACCESS_DENIED_ERROR",
"errno": 1045,
"sqlMessage": "Access denied for user 'username'#'ec2-54-170-17-28.eu-west-1.compute.amazonaws.com' (using password: YES)",
"sqlState": "28000",
"fatal": true}
If I'm not mistaken, the '#'ec2-54-170-17-28.eu-west-1.compute.amazonaws.com' is not supposed to be included in the login information and it was not passed in where the DB connection is referenced.
I don't know if this is enough information so please ask for anything that may be needed. Appreciate any assistance.
I can see that you haven't specify the port. While connecting to a remote database from Heroku you should use these fields:
host: 'localhost',
port: 3306,
user: 'root',
password: '',
database: 'db_name',
insecureAuth: true
there is a one option also that you created a connection string like
DATABASE_URL=mysql2://username:password#ip.goes.here/data_base_name --app heroku-app-name
and specify it in your .env fil.
This makes the process lot more easier.
I realised that Hostgator has IP whitelisting rules for remote access to the hosted SQL servers. So Heroku wasn't appending anything to the connection, the server was actually responding saying the connection isn't allowed from the requesting hostname.
I appreciate all the help and I'm sorry for wasting the time of those who helped out.

MQTT unable to connect over TLS

I'm trying to connect to a MQTT broker over TLS in react-native with MQTT.js. Based on the doc I tried this code:
const options = {
port: PORT,
host: HOST,
protocol: 'mqtts',
secureProtocol: 'TLS_method',
username: USERNAME,
password: PASSWORD,
ca: CA_FILE
}
const client = mqtt.connect(options);
client.on('error', (error) => {
console.log("error", error);
});
client.on('connect', () => {
console.log("connected");
});
The options object will be passed through tls.connect(), so I specified the certificate file.
The connection doesn't return an error, but the client is not connected.
What did I do wrong?
Try to use that fork of React native MQTT https://github.com/FrozenPyrozen/rn-native-mqtt it worked with TLS connection on Android and IOS

Websocket connection error: returns 101, but does not upgrade

I am setting up some websockets using ws library. I am struggling to set up authorisation using a handshake. I have added a route to our server to upgrade to a websocket connection like so:
.get(
'/chat',
authorisationFunction,
upgradeConnection,
),
The websocket server:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3030 });
This is the upgradeConnection function, which will run if authorisation is successful:
const upgradeConnection = (request, socket, head) => {
return wss.handleUpgrade(request, request.socket, head, function done(ws) {
return wss.emit('connection', ws, request);
});
}
I also have a function that listens to messages:
function webSocketsServer() {
wss.on('connection', (ws, request, client) => {
ws.on('message', message => {
ws.send(message);
});
});
}
A connection gets emitted, and from my server I get this response:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: QyVvqadEcI1+ALka6j2pLKBkfNQ=
but then immediately on my client I get the error “WebSocket connection to 'ws://localhost:3000/chat’ failed: Invalid frame header”.
But when I bypass the handshake and connect directly to my websocket server, I can send messages successfully. The error is only on the client and not on the backend. What am I missing?
I am not 100% sure it is the only way but might help so I post it.
Based on this answer I would go for a server that uses the same port for http and websocket connections.
You can achieve it like this:
const { createServer } = require('http')
const ws = require('ws')
const express = require('express')
const app = express()
const server = createServer(app)
app.get('/', (req, res) => {
res.send('I am a normal http server response')
})
const wsServer = new ws.Server({
server,
path: '/websocket-path',
})
wsServer.on('connection', (connection) => {
connection.send('I am a websocket response')
})
server.listen(3030, () => {
console.log(`Server is now running on http://localhost:3030`)
console.log(`Websocket is now running on ws://localhost:3030/<websocket-path>`)
})
So your server listens on port 3030 for normal http requests. If it gets a websocket connection request on path '/websocket-path' it is passed to the the ws connection handler and from there you are good to go.

Connect to MySQL using SSH Tunneling in node-mysql

When using the node-mysql npm package, is it possible to connect to the MySQL server using a SSH key instead of a password?
You can do the SSH tunnel component completely independently, and then point node-mysql (or any other sql client...) to your DB by using TCP tunneled over SSH.
Just set up your SSH tunnel like this
ssh -N -p 22 sqluser#remoteserverrunningmysql.your.net -L 33306:localhost:3306
Leave that going in the background (see articles like this for more in depth info).
Then just send any MySQL client to port 33306 on localhost. It will actually connect as though you are on your remote server and using port 3306.
Thanks so much Steve your answer help me alot. just to make it clearer use
ssh -f user#personal-server.com -L 2000:personal-server.com:25 -N
The -f tells ssh to go into the background just before it executes the command. This is followed by the username and server you are logging into. The -L 2000:personal-server.com:25 is in the form of -L local-port:host:remote-port. Finally the -N instructs OpenSSH to not execute a command on the remote system
To connect to mongo use whatever port you set as Local port (in this case the port is 2000)
For example let's say I want to connect on a remote server with IP 192.168.0.100 and mongo is running on port 27017.
Assume a user called elie with password eliepassword has access to ssh on port 22 I will have to do this
First run on the terminal the following :
ssh -f elie#192.168.0.100 -L 2002:127.0.0.1:27017 -N
In my mongo connection I will do :
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:2002/mydatabase');
module.exports = mongoose.connection;
I hope this makes it clear.
const mysql = require('mysql2');
const { Client } = require('ssh2');
const sshClient = new Client();
const dbServer = {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE
}
const tunnelConfig = {
host: process.env.DB_SSH_HOST,
port: 22,
username: process.env.DB_SSH_USER,
password: process.env.DB_SSH_PASSWORD
}
const forwardConfig = {
srcHost: '127.0.0.1',
srcPort: 3306,
dstHost: dbServer.host,
dstPort: dbServer.port
};
const SSHConnection = new Promise((resolve, reject) => {
sshClient.on('ready', () => {
sshClient.forwardOut(
forwardConfig.srcHost,
forwardConfig.srcPort,
forwardConfig.dstHost,
forwardConfig.dstPort,
(err, stream) => {
if (err) reject(err);
const updatedDbServer = {
...dbServer,
stream
};
const connection = mysql.createConnection(updatedDbServer);
connection.connect((error) => {
if (error) {
reject(error);
}
resolve(connection);
});
});
}).connect(tunnelConfig);
});

Categories

Resources