Issue with a 404 error using socket.io - node.js

I've recently gotten into socket.io, during a long-term project of mine. Which is probably why I am having such a hard time of it, because their "getting started" sections don't take into account you may already be deep into development of your own application. The main issue is it connecting, it won't do it, client-side that is.
I keep getting a 404 not found which is cause by CANNOT POST /socket.io/ Which it is right, it can't obviously, mainly because that is not where the socket.io location is (it is in node_modules per usual). Secondly if I create a route for this, it does absolutely nothing. So here is code initializing it:
/*jshint esversion: 6*/
const express = require('express');
const http = require('http');
const bodyParser = require('body-parser');
const path = require('path');
const expressValidator = require('express-validator');
const flash = require('connect-flash');
const session = require('express-session');
const passport = require('passport');
const db = require('./config/db');
// Init App
const app = express();
// Init http server
const server = http.createServer(app);
// init socket
const io = require('socket.io').listen(server);
Here is the clientside trying to connect to it:
if (window.location.hostname == 'playkog.net' || window.location.hostname == 'www.playkog.net') {
var port = 443;
} else {
var port = 8080;
}
var connected = false;
var socket = io.connect(window.location.hostname + ':' + port, { 'connect timeout': 5000 });
// Connection Successful
socket.on('connect', function () {
console.log('a user connected');
connected = true;
});
socket.on('disconnect', function () {
console.log('user disconnected');
connected = false;
});
I imagine I'll have to connect to a different port, however I'm not sure which, nor if that is my issue (or only issue). Of course be extremely new to this kind of stuff (amateur at best) some of these things just go right over my head.
Here is a screenshot of my console

Related

Passing an object from a main server.js file down to a controller

I'm making a basic restaurant ordering web app for fun/learning purposes using node/express for my backend and react as my frontend. I've based my app on a mix of various YT tutorials including the ones Dave Gray to structure my project.
Currently I'm at the stage where I'm trying to implement notifications using SocketIO (the idea that the server will push notifications down to the clients to notify them of certain events such as an order being made).
My current progress is here: https://github.com/kevin-rph-lee/noodlebox/tree/socket-notifications
The issue I'm having is I'm trying to figure out the best way to pass my SocketIO object down to one of my controllers (specifically the orders controller).
My current structure is:
server.js --> orders.js (route) --> ordersController.js (controller)
Currently in my main server.js file I have initialized the io object for SocketIO (as seen below)
require('dotenv').config();
const WebSocketServer = require("ws").Server
var http = require("http")
const express = require('express');
const path = require('path');
const PORT = process.env.PORT || 3001;
const app = express();
const morgan = require('morgan');
const cors = require('cors');
const corsOptions = require('./config/corsOptions');
const credentials = require('./middleware/credentials');
const cookieParser = require('cookie-parser');
// Creating a new socketio server
const server = require('http').createServer(app);
const io = require('socket.io')(server);
//Numbers of users connected. Initially 0
let clientsConnected = 0
io.on('connection', function(socket){
//Client connecting, incrementing client counter
clientsConnected++
console.log('Client connected. Total clients connected ' + clientsConnected)
//When a message is recieved from a client, echo it to all other clients connected
socket.on("message from client", (arg) => {
console.log('reieved')
console.log(arg)
// socket.broadcast.emit('message to client', arg)
// socket.to(1).emit('message to client', 'enjoy the game')
io.in(1).emit('message to client', 'enjoy the game')
});
socket.on("join", (userID) => {
socket.join(userID)
console.log('Rooms:')
console.log(socket.rooms)
});
socket.on("leave", (userID) => {
socket.leave(userID)
console.log('Rooms:')
console.log(socket.rooms)
});
//Deincrement the counter when the client disconnects
socket.on("disconnect", (reason) => {
clientsConnected--
console.log('Client connected. Total clients connected ' + clientsConnected)
});
})
// PG database client/connection setup
const { Pool } = require('pg');
const dbParams = require('./lib/db.js');
const db = new Pool(dbParams);
db.connect();
// Load the logger first so all (static) HTTP requests are logged to STDOUT
// 'dev' = Concise output colored by response status for development use.
// The :status token will be colored red for server error codes, yellow for client error codes, cyan for redirection codes, and uncolored for all other codes.
app.use(morgan('dev'));
app.use(credentials);
app.use(cors(corsOptions));
app.use(express.json()); // => allows us to access the req.body
//middleware for cookies
app.use(cookieParser());
if (process.env.NODE_ENV === 'production') {
//server static content
//npm run build
app.use(express.static(path.join(__dirname, 'client/build')));
}
console.log(__dirname);
console.log(path.join(__dirname, 'client/build'));
// Separated Routes for each Resource
const usersRoutes = require('./routes/users');
const refreshRoutes = require('./routes/refresh');
const menuItemsRoutes = require('./routes/menuItems');
const ordersRoutes = require('./routes/orders');
// Resource routes
app.use('/users', usersRoutes());
app.use('/refresh', refreshRoutes());
app.use('/menuItems', menuItemsRoutes());
app.use('/orders', ordersRoutes());
// All other GET requests not handled before will return our React app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '/client/build/index.html'));
});
server.listen(PORT);
I am now trying to figure out how to pass the io object down to my orders route, and then from the route to the controller.
Within server.js, to pass io down to the route it was thinking it would be something like...
app.use('/orders', ordersRoutes(io));
But within the order route itself I get stuck
order.js
const express = require('express');
const router = express.Router();
const ordersController = require('../controllers/ordersController')
const verifyJWT = require('../middleware/verifyJWT')
const verifyRoles = require('../middleware/verifyRoles');
module.exports = () => {
//Get order
router.route('/')
.get(verifyJWT, verifyRoles('user', 'admin'),ordersController.getOrders)
//Create order
router.route('/')
.post(verifyJWT, verifyRoles('user', 'admin'), ordersController.createOrder)
return router;
};
To receive the io object from server.js I'm thinking I would need to modify the module.exports line so it would look like:
module.exports = (io) = {
but at that point I'm stuck on how I can pass it down one more layer from the route file to the controller file. The idea is I want the io functionality (e.g broadcasting a SocketIO message) to be available to me within the controllers file. In particular I want the ability to broadcast a message when a certain axios request is made from a connected client (e.g broadcast a SocketIO message when an axios POST request is made to create an order).
I was hoping someone could help me out with a potential way to move forward, or let me know if I'm going down the completely wrong path.
Thank you

socketio, client can connect to server if hosted locally, but returns error when trying to connect to server hosted on seperate vserver

I am trying to make a simple server with socket.io and express and connect to it through a website.
when i followed a tutorial on socketio with localhost, everything worked fine, but when i put the server on a vserver, and tried to connect to it, i got this error:
Failed to load resource: net::ERR_SSL_PROTOCOL_ERROR
as well as:
GET https://54.53.0.254:47185/socket.io/?EIO=4&transport=polling&t=O09jjrs net::ERR_SSL_PROTOCOL_ERROR
here is my server code:
const express = require('express');
const app = express();
const server = app.listen(47185);
const socket = require('socket.io');
const io = socket(server)
console.log('server running on port 47185');
io.sockets.on('connection', newConnection);
function newConnection(socket) {
console.log('new connection: ' + socket.id);
socket.on('input', inputLog)
function inputLog(data) {
socket.broadcast.emit('input', data);
console.log(data);
}
}
and here is my client code (this is all that relates to socket.io, the rest is just for the website)
var options = {
rejectUnauthorized:false
}
var socket;
socket = io.connect('89.58.0.199:47185', options);
socket.on('input', foreignInput)
function foreignInput(data) {
terminal_animate('\n' + data)
}
i have tried many different fixes and googled everything i can think of, and i'm just not sure what the problem is.
can anyone help me out with this issue? thanks in advance.
In the documentation, according to the Client Initialization part, in node.js you should provide the protocol when connecting to the server.
// the following forms are similar
const socket = io("https://server-domain.com");
const socket = io("wss://server-domain.com");
const socket = io("server-domain.com"); // only in the browser when the page is served over https (will not work in Node.js)
The first two example shows the secure https/wss as protocol, for that you need to serve the required files from the server, example in the documentation.
With http/ws as protocol it should work, but the communication will not be secure.
The Server Initialization / With Express shows an example to call .listen on the return value of createServer from the http module, with the app given as a parameter.
const express = require("express");
const { createServer } = require("http");
const { Server } = require("socket.io");
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer, { /* options */ });
io.on("connection", (socket) => {
// ...
});
httpServer.listen(3000);
With a caution that says:
Using app.listen(3000) will not work here, as it creates a new HTTP server.

Broadcast a basic event to all clients

How would I go about broadcasting alert("Hello World!"); on all clients currently avaible?
I have gone through these links:
https://socket.io/get-started/chat
https://socket.io/docs/v3/client-api/
https://socket.io/docs/v3/emit-cheatsheet/
And NONE of them helped. Can someone please help me?!
Solutions I have tried:
// Script.js:
var socket;
function onload(){
socket = io();
}
function test(){
socket.emit("broadcast");
}
socket.on('broadcast', function() {
alert("Hello World!");
});
// index.js:
const express = require("express");
const socketio = require("socket.io");
const path = require("path");
const app = express();
const http = require("http");
const io2 = require("socket.io-client");
const directory = path.join(__dirname, "html");
const httpserver = http.Server(app);
const io = socketio(httpserver);
app.use(express.static(directory));
httpserver.listen(3000);
To broadcast a message to all connected clients from your server, you do:
io.emit('bulletin', someMsg);
To listen for that message in the client, you do this:
socket.on('bulletin', someMsg => {
console.log(someMsg);
});
The message name 'bulletin' can be anything you want it to be (any string that doesn't conflict with a built-in message name).
You cannot trigger a broadcast directly from the client. But, you can send the server a custom message that you design and have the server, upon receipt of that message, then do a broadcast to all connected clients.

Show console.log message with socket.io and Express.js on Node.js

I'm trying to see a console.log message without results from the socket when someone connects to application. Here is what i have on /app.js and /bin/www files:
Just a way to return a message on console for check if the socket works on
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var morgan = require('morgan');
var mongoose = require('mongoose');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var session = require('express-session');
var socket = require('socket.io');
var app = express();
// socket.io
var io = socket();
app.io = io;
// var for routes
var index = require('./routes/index');
var users = require('./routes/users');
var projects = require('./routes/projects');
var messages = require('./routes/messages');
//socket message
io.on( "connection", function(socket){
console.log( "A user connected" );
});
www
var app = require('../app');
var debug = require('debug')('archiers:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
// socket.io
var io = app.io;
io.attach(server);
It would seem that you are working with some example code (rather than having written all of that yourself).
The example code you are using is quite a bit longer than it needs to be to accomplish your goals this early on.
For one thing your app.js is not "listening" on any port number - so it cannot possibly get a connection to work.
I can see your www js file would have to cause an error with process.env because the browser has no such variable.
Since you are not getting an error in your browser Console that means there must be a problem with the HTML file (which you have not posted thus far.
I expect there are other problems with the example code you are using that I have not seen.
Since you do not yet understand enough details of the code, I would suggest you start over.
You need to start with a smaller project.
Search the internet for a very small io.js example that works when you download and run it and go from there.
It will be much easier that way.

Need for module.parent in the following node.js code

const PORT = 3000;
const HOST = 'localhost';
var express = require('express'),
http = require('http'),
server = http.createServer(app);
var app = express();
const redis = require('redis');
const client = redis.createClient();
const io = require('socket.io');
if (!module.parent) {
server.listen(PORT, HOST);
const socket = io.listen(server);
socket.on('connection', function(client) {
const subscribe = redis.createClient()
subscribe.subscribe('realtime');
...
...
});
});
}
I stumbled upon this piece of code in one of the sites , In the above code I want to know the reason why the condition (!module.parent) is used ??? Whats the need for using it ??
If there is no module.parent it probably means that the module is being run on its own rather than being used in another program. If the !module.parent block is in a utility module I would guess that it is code for a test or developer tool. In a program that does stuff on it's own (e.g. a webserver), it would probably be the main entry point and the purpose of using it would be to make it possible to require components of that program without running the program.

Resources