Socketio won't connect from hosted site to droplet - node.js

I have a digital ocean droplet that is running a nodeJS server being run with pm2. When I run my preact app locally with the io.connect set to
io.connect('app.ardilabs.com:9080');
app.ardilabs.com is where the nodeJS server lives.
The locally run web app will connect to the remote server from D.O. and then will update my app with the data I am POSTing using Postman.
When I try to build the app and put it on the same D.O droplet and serve the app using nginx the app will load when you go to the URL but it won't connect to the nodeJS server. When I try to POST something I get a confirmation from the server that it got my data but it's never forwarded to the app.
Why does it work locally and with a remote server but not when I am hosting the app and serving it with nginx? I am really stumped.
Here is the relevant server code:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
// routes will go here
io.on('connection', function(socket){
//We need a connection but we don't need to do anything about it
});
// start the server
http.listen(9080, function() {
console.log('listening on *:9080');
});
Here is the relevant client code:
import io from 'socket.io-client';
const socket = io.connect('app.ardilabs.com:9080');
A few extra notes:
I am using nginx as my web server
My site has a cert from Let's Encrypt
If I am missing any info needed please let me know!

I figured out what the issue was.
Once I put a cert on my nginx server I didn't realize that I needed to configure my express server to also use HTTPS. Once I enabled HTTPS on the express server the data went through to the connected web app just fine.

Related

Express-Socket.IO App isn't working with my Azure WebApp

For educational purposes I try to deploy an Express Server that is using Socket.IO. The Server should be able to deliver a static HTML Site that was built with React, answer with a "Hello Azure!" message whenever I make a GET Rest Call to http://localhost:4000/api/azure and whenever a new client connects to the site, all the other clients get a message announcing the new client.
const path = require('path');
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
const router = require('./api/azure');
const PORT = process.env.PORT || 4000;
io.on('connection', () => {
console.log('A new user has connected!')
io.emit('broadcast', 'A new user has connected');
});
app.use(express.json());
app.use('/api/azure', router);
app.use(express.static(path.join(__dirname, 'build')));
app.use(express.static('public'));
app.use('/', (_, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
server.listen(PORT, () => {
console.log(`Listening to http://localhost:${PORT}`);
});
All this tasks are fulfilled without problems in localhost. The problem begins after this app is uploaded to one of my Azure WebApps.
Instead of delivering the message "Hello Azure!" when I call the https://mydomain.azurewebsites.net/api/azure it responses back with the HTML file.
The typical Socket.IO GET method for polling
https://mydomain.azurewebsites.net/socket.io/?EIO=4&transport=polling&t=SomeString
responses back with the HTML file, too.
Everything url extension that I give, gives me back the HTML file.
I barely know the basic stuff about WebApps. Maybe there is a configuration that I am forgetting? By the way I haven't done anything in the configuration except that I enabled the Websockets in the WebApp config.
This never happened before. The only difference is that right now I am using a free-tier just to test. Could it be that? If not, what am I doing wrong?
Thank you for your time!
To begin with, try turning the Web Socket config off as it applies to an IIS setting which tends to contradict with the Node.js websocket implementation.
If this doesn't help, try and force the transport layer to use Websockets and SSL.
io.configure(function() {
// Force websocket
io.set('transports', ['websocket']);
// Force SSL
io.set('match origin protocol', true);
});
Also, you cannot use arbitrary ports (port 4000 in your case) on services like App Service. Your app will be provided a port via process.env.PORT. So ensure that you are refering to the correct port from your log message. You should be able to see these in your log stream.
Also note, that Azure has launched a fully managed service called Web PubSub to power your apps with Web Sockets. The app service web socket implementation does not scale horizontally, this where Web PubSub will help you.
https://azure.microsoft.com/en-in/blog/easily-build-realtime-apps-with-websockets-and-azure-web-pubsub-now-in-preview/

404 - from nginx application to remote servers localhost?

I am new to react, and wanted to deploy a site to my domain with Nginx. I need to make the application to be able to fetch from client side, to the localhost of the remote server hosting the site with Nginx. I know exposing this many details might make security experts and hackers either drool or shake their heads. But I am losing my sanity from this.
This is a filtered version of my Node.js express service running on the remote server:
const express = require("express")
const cors = require("cors")
const app = express();
const PORT = 1234;
const spawn = require("child_process").spawn;
app.use(cors())
app.listen(PORT, function(){
console.log(`listening on port:${PORT}...`)
})
app.get("/api/play/:choice", function(req,res){
pythonProcess = spawn('python',["./script.py", req.params.choice]);
pythonProcess.stdout.on('data', function(data) {
res.status(200).send(data.toString('utf-8'))})
})
this is how I am fetching from the deployed react application. The public IP of the droplet I am using
fetch(`104.248.28.88/1234/api/play/rock`)
Change the fetch to replace the / with a : to indicate port, rather than directory
fetch("104.248.28.88:1234/api/play/rock")

Between Node.JS and Express, can someone explain where the Web Server fits in?

I've recently started server-side development using Node JS and Express but i'm getting confused as to how it all works. From my understanding, The web serve stores the website and returns the pages as they're requested from the browser. Apache is a web server and you would use that for a stack like XAMPP. ASP.NET is a framework that uses IIS Web Server and communicates with that.
But with Node, where's the server? Node is runtime environment and is USED to CREATE a server and Express is a web FRAMEWORK to help with server http requests but what/where is the actual web SERVER? Maybe i'm just not understanding web servers or something? Someone please clarify!
For Node, we do not need a web server like Apache or a container that sort of, node can listen to a port and act as a server itself,
and express is web application framework for Node which provides set of features to make life easier.
for a vague comparison, if Node is a telephone then Node + express will be a smartphone. - both can do same stuff but latter have more convenient features.
see below two example of creating a server which listen to a port 3000,
In node:
const http = require('http')
const requestHandler = (request, response) => {
console.log(request.url)
response.end('Hello Node.js Server!')
}
const server = http.createServer(requestHandler)
server.listen(3000,() => console.log("app started"));
Node + express
const express = require('express');
const app = express();
app.get('/', function (req, res) {
res.send('Hello express !')
})
app.listen(3000,() => console.log("app started"));
Both does the same thing, but with express things are easier.

Connecting to NodeJS server from apache served page

So basically I have a webpage runned by apache on port 1900 and I have a NodeJS server running on port 3000.
Server code:
var express = require('express');
var http = require('http');
//make sure you keep this order
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var port = 3000;
server.listen(port, '192.168.0.105', function(){
console.log('Server started: listening on port '+port+'.');
});
On the webpage a have the following code:
var socket = io('192.168.0.105:3000'); which connects to the NodeJS server when loading the page from the computer that runs the server(my laptop) and apache.
The problem appears when I try to access the webpage from another computer(laptop) connected to the same LAN that the laptop running the server is.
When I access 192.168.0.105:1900 from that laptop, I only see the page that is being loaded from apache but doesn't connect to the NodeJS server, it tries to connect to 192.168.0.105:3000 forever but fails after 1 minute.
How do I resolve this problem?
Thank you.
Making my comment into an answer since it solved the problem.
Windows 7 has a built-in personal firewall by default. You may have to enable connections to port 3000 manually. The router is presumably for access from outside the network. You're talking about accessing from your laptop when on the same LAN so that would more likely be the built-in personal firewall.

Node.js hosting with Socket.io client support?

I made a socket.io client app which connects to my socket.io server and then they communicate whatever they need to.
When I do it locally on one machine or even on two different local machines, everything works fine. So I tried to deploy the client on cloud9 and it keeps throwing this error:
net.js:540
connectReq = self._handle.connect(address, port);
Error: No local connects allowed for security purposes
at connect (net.js:540:31)
at net.js:607:9
at Array.0 (dns.js:88:18)
at EventEmitter._tickCallback (node.js:190:38)
The client code is, where [ip-address] is my servers IP address:
var io = require('socket.io-client'),
socket = io.connect('[ip-address]', {
port: 1337
});
Is there a way to run such a socket.io client at c9.io?
Did they block it because of this article?
Are there any free node.js hosting solutions where one could run a socket.io client application like the one above?
Thanks.
Depending on your needs you could create a free Heroku account. You wont have access to a database, and you're limited in resources, but if the app is small enough and efficient enough it could suffice.
Nodejitsu is currently free node.js hosting solution where everything works (including socket.io)
OpenShift uses Port 8080 and Heroku 3000.
The Client code has to be like this:
// Wrong!:
// mySocket = io.connect(host, port);
// Right:
mySocket = io();
mySocket.on(....);
The Server code has to look like this:
var express = require('express'),
app = express(),
server = require('http').Server(app),
io = require('socket.io')(server);
app.use(express.static('path/to/public/html'));
server.listen(8080); // OpenShift 8080, Heroku 3000
io.on(...);
https://devcenter.heroku.com/articles/node-websockets#create-a-socket-io-client

Resources