serving client + socket io from backend - javascript

Serving a vue js + socket io client from a node js server (with socket io obviously)
while developing i was connecting and awaiting calls from localhost:8000
new Websocket(
new Server(server, {
cors: {
origin: "http://localhost:8000",
methods: ["GET", "POST"],
},
}),
);
but now, obviously, there is no longer localhost:8000 and I am serving my client's dist/index.html through my webserver as a static file
app.use(express.static(path.join(__dirname, "../../client/dist")));
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "../../client/dist/index.html"));
});
I feel like I am missing something really really simple? am I supposed to host my client on a different "web server" if i want to use the socket.io functionality?
as in create a simple web server for the client - and serve it from there on port 8000? and run my own server seperatly ? on port 3000?
I'm hosting this on an EC2 container on aws

I've figured it out - I need to connect to the machine's ip instead of localhost through the client's app - cause localhost:3000 doesn't actually exist...otherwise everything else is ok

Related

How to keep socket.io client in frontend code

I am just learning webdev and want to try to make a multiplayer game using Express and socket.io
I can make a server with socket.io in it which listens. That part works fine.
However when I try to connect a client, this only works if I let the HTML file with the following in it be served by the server like follows:
Server code:
const express = require('express')
const app = express()
const http = require('http')
const server = http.createServer(app)
const { Server } = require('socket.io')
const io = new Server(server)
const port = 3000
io.on('connection', (sock) => {
console.log('client connected')
})
// This seems to be necessary, but I don't want it to be!!!
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
})
server.listen(port, () => {
console.log(`Server listening on port ${port}`)
})
This index.html has the following at the bottom:
<script src="/socket.io/socket.io.js"></script>
<script>const socket = io()</script>
However I want to keep all my frontend code seperate from the server. I made a seperate repository for the frontend and backend. I want the frontend to contain all the UI logic and use only data calls (AJAX) to get Json data from the server. So I want to put this index.html file in my frontend code only.
Yet if I do this the connection doesn't work.
I can start the server fine.
I open index.html from WebStorm which also creates a server for this which I configured to also listen to port 3000
Yet it cannot find /socket.io/socket.io.js and I get the following error in the console.
It also doesn't work if WebStorm runs on a different port.
The resource from “http://localhost:3000/socket.io/socket.io.js” was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff).
How can I keep this html in my client repo only and still work with socket.io, or is this not possible?
You can't have multiple servers listening on the same port. Run the servers on different ports and either:
Have a reverse proxy forwarding requests to your Socket.io server (which needs special handling) and your front end server or
Put an absolute URL in the script src and configure CORS.

Node.js + Apache - https://localhost:3000/socket.io/ ERR_CONNECTION_REFUSED

I am implementing a simple game in Node.js. I have a client.js for my client side code, and a server.js running on a remote server, which both use sockets to communicate on port 3000
I am also running Apache on port 80, and using ProxyPass in my apache configuration file, to route the url mywebsite.io/agario to my nodejs server.
<Location /agario>
ProxyPass http://localhost:3000/
ProxyPassReverse http://localhost:3000/
</Location>
I am also using cloudflare to route my webserver 167.179.xx.xx through the url https://agario.mywebsite.io for SSL so that I can use HTTPS.
The problem
When I try to connect to my website https://agario.mywebsite.io/agario I am receiving the following error:
socket.io-1.4.5.js:1 GET https://localhost:3000/socket.io/?EIO=3&transport=polling&t=MakAMgZ net::ERR_CONNECTION_REFUSED
I am unclear why my client code is trying to connect to localhost, when I have specified in the code to connect to the remote server. Potentially I am just confused on how to run the node.js server as this is my first taste of Node.js and sockets.
client.js
...
var socket;
socket = io.connect('https://agario.mywebsite.io/agario');
...
server.js
var app = express();
var server = app.listen(3000, listen);
// This call back just tells us that the server has started
function listen() {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://' + host + ':' + port);
}
app.use(express.static('public'));
var io = require('socket.io')(server);
io.sockets.on('connection',
function(socket) {
console.log("We have a new client: " + socket.id);
...
});
If I have missed out any vital information please let me know and I will update my question, thank you.
You server is listening on port 3000 and you're trying to connect with it via 443, you should try something like this
socket.connect('https://ip:3000');
However, if you're sure that ur client is using the same port as the server or u have a port forwarding then try to use netcat just to make sure the the problem is with your script not the network config :
nc -zv -w1 ip port

Can't access node.js webserver with godaddy shared hosting URL

When I enter www.example.com:3000 in the browser, I receive this error (where 'example' is the name of my domain)
This site can't be reached - www.example.com took too long to respond.
I have done these things:
Installed node.js on my GoDaddy shared account
Created a folder ../public_html/testsite
Placed two files in that folder: app.js and .htaccess.
Start webserver with: node app.js
Go to browser and enter my domain's URL and port:
Receive the error message above
This post is very helpful, but I still cannot get my set up to work.
These two files are in ../public_html/testsite/
.htaccess
RewriteEngine on
RewriteRule ^index.html.var$ http://www.example.com:3000/$1 [L,P,QSA]
RewriteRule (.*) http://www.example.com:3000/$1 [P,L]
Note: index.html is the file that normally loads when you visit here
The app.js:
const http = require('http');
const hostname= '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('NodeJS server running on Shared Hosting\n');
});
server.listen(port, hostname, () => {
console.log('Server running at http://' + hostname + ':' + port + '/');
});
To start the webserver:
> cd ../public_html/testsite
> node app.js
Server running at http://127.0.0.1:3000
In browser, I enter:
www.example.com:3000
I expected to see, in the browser
NodeJS server running on Shared Hosting
Questions:
Should I use my own godaddy domain address for hostname in .htaccess or should it be localhost?
Is the idea to redirect www.example.com:3000 (in browser) to http://localhost:3000 (on GoDaddy server)?
I've tried all sorts of permutations (using my ip address or domain name, different port numbers, etc.)
I think I am close, but need a few ideas to try!
Port 3000, 8080, and the likes are normally used for development purposes, as in development in can be useful to have several servers running at the same time, for example one on port 3000, one on port 3001, etc.
However, on the internet, HTTP is served on port 80 and HTTPS is served on port 443. So basically, in your server implementation, you should set the port dynamically: it must not be the same whether you're running in production and in development!
I personally use the fact that on my production environment (ie for you, GoDaddy's deployment machines), the environment variable PORT is already set to 80, whereas on my local machine I don't set it, so I can write this:
const express = require('express');
const port = process.env.PORT || 3000; // 3000 on my machine, 80 on GoDaddy's server
const app = express();
app.listen(port, () => console.log(`App listening on port ${port}`));
And I access the server at these URLs:
http://localhost:3000/
http://example.com:80/
http://example.com/
The last two are the same because, as previously said, default HTTP port is 80.

how can I properly proxy requests to /api/ressource in prod?

I have a webpack dev configuration with my front end dev server running on 8080 and my backed server running on port 3000.
So in dev mode my webpack dev server is configured like follows :
proxy: {
'/api': 'http://localhost:3000',
}
How can I do the same thing in the prod server that serves the built static files of my front end ?
I have the following code for my prod server that serves the static files of my front end :
const proxy = require('http-proxy-middleware')
app.use(express.static(dir))
/**
* Redirect everything that starts with /api/* to the backend rest server
*/
app.use('/api', proxy({ target: backendUrl }))
app.get('*', (req, res) => {
res.sendFile(path.resolve(dir + '/index.html'))
})
This is not working as the cookies seem to be lost with the proxying (unlike with the proxying with webpack where evyrhthing works).
Am I going about this problem in the correct way ?
In this case, you can create a reverse-proxy which is going to receive all the information from the frontend, make the requests to the other address and then return the proper answer to the frontend. I used to develop a lot of these back in the days, there is a package that i created which can help you.
Basically the flow is:
Frontend -> endpoint on your render server (port 8080) -> backend (port 3000) -> render server (port 8080) -> frontend
You can try using:
A server (i.E. nginx) as a reverse proxy.
A node-http-proxy as a reverse proxy.
A vhost middleware if each domain is served from the same Express
codebase and node.js instance.
You may also want to check your cookie flags (changeOrigin, secure, cookieDomainRewrite etc..)
info: IF running http on localhost, the cookie will not be set if secure-flag is present in the response

Why heroku can't run WebSocket server without HTTP server?

I have a WebSocket app on heroku. I tried uploading my WebSocket app without routing http server but it doesn't work. What does mean server routing? And why can't heroku run a WebSocket server without an http server?
And why does it takes express object 'server' as argument in SocketServer
Here's my code of Websocket server.
const express = require('express');
const SocketServer = require('ws').Server;
const path = require('path');
const PORT = process.env.PORT || 3000;
const INDEX = path.join(__dirname, 'index.html');
const server = express()
.use((req, res) => res.sendFile(INDEX) )
.listen(PORT, () => console.log(`Listening on ${ PORT }`));
const wss = new SocketServer({ server });
wss.on("connection",function(ws){
ws.on("message",function(message){
if(message==='exit'){
ws.close();
}else{
wss.clients.forEach(function(client){
client.send(message);
});
console.log(message);
}
});
ws.send("welcome..");
});
There are too many questions in one. I hope my answers will address all of them.
First of all, the websocket protocol is an extension of http, it is not something different. Therefore, a websocket server is necessarily an http server, even though with extended capabilities.
Also, with socket.io, the websockets and http run on the same port. Therefore you have to open the port for http to have your websockets work.
Let's have a look at this line :
const wss = new SocketServer({ server });
It has a syntax error, it must be new SocketServer(server). Also, about the variable name, I would recommend not to use wss for a websocket over http, since wss stands for secure websockets and is related to websockets like http to https.
About routing in heroku: in heroku, you have to define which port your application is using. This can be compared to the firewall on your local machine : if you want to access it from outside, you have to open the port. On heroku, technically it is different to a firewall, but in this point it is similar.

Categories

Resources