io.sockets.on not working inside a route in Node.js - javascript

I'm trying to use io.sockets.on inside a route in a Node.js and Express app. I have been following what is said here: https://stackoverflow.com/a/31277123/8271839
I can successfully send io.sockets.emit events, but I cannot receive events with io.sockets.on.
Here is my code:
index.js:
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const taskRequest = require('./routes/taskRequest');
app.use(cors())
app.use(express.json());
app.use('/api/taskRequest', taskRequest);
app.set('socketio', io);
server.listen(4002);
io.sockets.on("connection",function(socket){
console.log("connected");
socket.on("connected", function (data) {
console.log("hello");
})
});
routes/taskRequest.js:
const express = require('express');
const router = express.Router();
router.post('/', async (req, res) => {
var io = req.app.get('socketio');
//pickedUser is one of the connected client
var pickedUser = "JZLpeA4pBECwbc5IAAAA";
//we only send the emit event to the pickedUser
io.to(pickedUser).emit('taskRequest', req.body);
io.on('connection', function (socket) {
console.log('connected 2');
socket.on('taskResponse', function () {
console.log('hello 2');
});
});
});
module.exports = router;
When a client is connected, I get the "connected" message in console, but not the "connected 2" message.
Also, when client emits "connected" message, I get "hello" in console, but when clients emits "taskResponse" message, I don't get "hello 2" in console.
Though when io.to(pickedUser).emit('taskRequest', req.body); is called, it works, client receives the "taskRequest" message.
Why is .emit() working inside my route but not .on() ?

According to you code, io is a Socket.IO server instance attached to an instance of http.Server listening for incoming events. Then inside the route you are again attaching a instance to listen to to incoming events which does not work. the io.to(pickedUser).emit works because the server instance with socketio is correctly listening to the connection thus giving the console.log("connected");.
index.js:
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const taskRequest = require('./routes/taskRequest');
app.use(cors())
app.use(express.json());
app.use('/api/taskRequest', taskRequest);
app.set('socketio', io);
server.listen(4002);
routes/taskRequest.js:
const express = require('express');
const router = express.Router();
router.post('/', async (req, res) => {
var io = req.app.get('socketio');
//pickedUser is one of the connected client
var pickedUser = "JZLpeA4pBECwbc5IAAAA";
io.on('connection', function (socket) {
console.log('connected 2');
io.to(pickedUser).emit('taskRequest', req.body);
socket.on('taskResponse', function () {
console.log('hello 2');
});
});
});
module.exports = router;

I mark TRomesh answer as the right answer, since indeed you can only have one io.on('connection', function (socket) {}) in your code.
Now here is what I have done to make it work for me: the issue was that if you place io.on('connection', function (socket) {}) within your router.post('/', async (req, res) => {}), it will only be triggered when you call your endpoint. In my case, I had some sockets events that I wanted to be called at anytime, not only when the endpoint is called. So I had to place the io.on('connection', function (socket) {}) outside of my router.post('/', async (req, res) => {}). Thus I couldn't use var io = req.app.get('socketio'); inside the router. Here is what I have done instead:
index.js:
const cors = require('cors');
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const taskRequest = require('./routes/taskRequest')(io);
app.use(cors())
app.use(express.json());
app.use('/api/taskRequest', taskRequest);
server.listen(4002);
routes/taskRequest.js
const express = require('express');
const router = express.Router();
module.exports = function(io) {
//we define the variables
var sendResponse = function () {};
io.sockets.on("connection",function(socket){
// Everytime a client logs in, display a connected message
console.log("Server-Client Connected!");
socket.on('connected', function(data) {
//listen to event at anytime (not only when endpoint is called)
//execute some code here
});
socket.on('taskResponse', data => {
//calling a function which is inside the router so we can send a res back
sendResponse(data);
})
});
router.post('/', async (req, res) => {
//pickedUser is one of the connected client
var pickedUser = "JZLpeA4pBECwbc5IAAAA";
io.to(pickedUser).emit('taskRequest', req.body);
sendResponse = function (data) {
return res.status(200).json({"text": "Success", "response": data.data});
}
});
return router;
};

Related

Node js with express and socket.io -can't fint socket.io.js

So basically what i am trying to do is build a chat app with a login system but for some reason i cant put it together and i am getting an error when i join to the room the chat.hbs can't find the socket.io.js file and also the main.js is getting a reference error with the const socket = io(); (the chat app works fine without the login system)
Failed to load resource: the server responded with a status of 404 (Not Found)
Uncaught ReferenceError: io is not definedat main.js:11
This is the app.js file
const express = require("express");
const path = require('path');
const http = require('http');
const socketio = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
const botName = "Bot";
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.urlencoded({ extended: false }));
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
app.use(cookieParser());
app.set('view engine', 'hbs');
//eldönti az útvonalat
app.use('/', require('./routes/pages'));
app.use('/auth', require('./routes/auth'));
app.listen(5001, () => {
console.log("Server started on Port 5001");
})
This is the main.js
const chatForm = document.getElementById('chat-form');
const chatMessages = document.querySelector('.chat-messages');
const roomName = document.getElementById('room-name');
const userList = document.getElementById('users');
// Felhasználó név és szoba név URL-ből
const { username, room } = Qs.parse(location.search, {
ignoreQueryPrefix: true,
});
const socket = io();
// Csatlakozik chat szobába
socket.emit('joinRoom', { username, room });
// Lekérdezi a szobát felhasználókat
socket.on('roomUsers', ({ room, users }) => {
outputRoomName(room);
outputUsers(users);
});
And the chat.hbs
<script src="/socket.io/socket.io.js"></script>
<script src="/main.js"></script>
Well the problem was that I used:
app.listen(5001, () => {
console.log("Server started on Port 5001");
})
instead of:
server.listen(5001, () => {
console.log("Server started on Port 5001");
})
Szia, you will need to wait for the DOM to load.
window.addEventListener('load', function () {
// Your code goes here
const socket = io();
socket.on("connect", () => {
// you can only emit once the connection is established.
socket.emit('joinRoom', { username, room });
});
})

Socket.io server on "connection" not firing, same for the client event not firing

Hi tried to build an express backend using socket io but for whatever reason I just dont get the connection events to be fired. I am using version 3.1.2 on the server and client, so thats not the issue. As soon as I start the client app, I get some log in the express server looking like this:
::ffff:127.0.0.1 - - [24/Oct/2021:11:14:10 +0000] "GET /socket.io/?EIO=4&transport=polling&t=Noo0Wgb&b64=1 HTTP/1.1" 404 149 "-" "node-XMLHttpRequest"
But the on connection event does not fire on either side.
const dotenv = require("dotenv").config();
const express = require("express");
const app = express();
const server = require("http").createServer(app);
const morgan = require("morgan");
const cors = require("cors");
const config = require("./src/config/general");
const io = require("socket.io")(server);
const SECURITY_KEY = process.env.SECURITYKEY;
//database
const connect = require("./src/config/database/connect");
app.set("json spaces", 2);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(morgan("combined"));
//controllers
const ExchangeController = require("./src/api/exchange/exchange.controller");
const exchangeController = new ExchangeController(io); //initially wanted to socket logic in that file, but even in the server.js its not working either
const LogController = require("./src/api/log/log.controller");
const logController = new LogController();
const StrategyController = require("./src/api/strategy/strategy.controller");
const strategyController = new StrategyController();
app.set("json spaces", 2);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(morgan("combined"));
app.use("/api/exchange", exchangeController.router);
app.use("/api/log", logController.router);
app.use("/api/strategy", strategyController.router);
io.on("connection", (socket) => {
console.log("incoming socket connection");
socket.on("buy", async (data) => {
try {
let payload = JSON.parse(data);
let symbols = payload.symbol.split(",");
let strategy;
if (payload.hasOwnProperty("strat")) {
strategy = payload.strat;
}
if (payload.security == SECURITY_KEY) {
for (let i = 0; i < symbols.length; i++) {
exchangeManager.performStrategy(strategy, symbols[i]);
}
}
} catch (error) {
console.log("io.on", error.message);
}
});
});
app.listen(config.PORT, async () => {
await connect();
console.log(`server started on port ${config.PORT}`);
});
Client side testing code
//client.js
const io = require('socket.io-client');
const socket = io("ws://localhost:3000")
// Add a connect listener
socket.on('connect', function (socket) {
console.log('Connected!');
});
socket.on('error', function (socket) {
console.log('error!');
});
I am completely lost on this and have tried everything without any success.
error solves by switching app.listen to server.listen, my bad.

Respond to client after receiving client to server POST request (Node.JS)

I have been attempting to respond to a client-side request with Node.JS. I have discovered Node JS - call function on server from client javascript, which seems to explain what I want, except that I can't seem to translate it to my program.
Here is the request via POST in index.html:
$.post("/", {data: 'hi'}, function(result){
$("body").html(result);
});
what I was hoping it would do would be write the result of the call, from my server.js (Node):
const express = require('express');
const path = require('path');
const http = require('http');
const fs = require('fs');
function handler(data, app){
if(req.method == "POST"){
app.setHeader('Content-Type', 'text/html');
app.writeHead(200);
app.end(data);
}
}
const BUILDPATH = path.join(__dirname);
const { PORT = 3000 } = process.env;
const app = express();
app.set('port', PORT);
app.use(express.static(BUILDPATH));
app.get('/*', (req, res) => res.sendFile('static/index.html', { root: BUILDPATH }));
const httpServer = http.createServer(app);
httpServer.listen(PORT);
console.info(`🚀 Client Running on: http://localhost:${PORT}`);
try this code:
const express = require('express');
const path = require('path');
const http = require('http');
const fs = require('fs');
function handler(data, app){
if(req.method == "POST"){
app.setHeader('Content-Type', 'text/html');
app.writeHead(200);
app.end(data);
}
}
const BUILDPATH = path.join(__dirname);
const { PORT = 3000 } = process.env;
const app = express();
app.set('port', PORT);
app.use(express.static(BUILDPATH));
app.get('/', (req, res) => {
res
// best practice is to always return an status code
.status(200)
// just return an json object
.json({"msg": "ok, it all works just fine"})
});
const httpServer = http.createServer(app);
httpServer.listen(PORT);
console.info(`🚀 Client Running on: http://localhost:${PORT}`);
The issue is, is that the only route your Node server listens to is the one you define with /*. As you can see, that route returns your index.html file to the client. You did not specify a route that listens for a request that comes from the client.
To solve the issue, you will have to define a route that listens on a specific route for the request you are trying to make from your client.
I see you are using ExpressJS. here is the documentation on writing routes.

Passing a Socket.IO instance to route files

I am looking to share the a socket.io instance with my express route files.
I previously had the socket.io listener in one routes file, orders.js on port 5200 and the express server listening in app.js on port 5000, however my cloud service required me to use one port for both, so I did have moved them both to app.js. The code below has been drastically simplified to remove noise
./app.js
const port = process.env.PORT || 8000;
const socket = require('socket.io');
const server = app.listen(port, () => console.log(`[!] Listening on
port: ${chalk.green(port)}`))
const io = module.exports = socket(server);
app.use(express.json());
app.use(cors());
app.use('/', router)
./routes/index
const express = require('express');
const router = express.Router();
router.use('/orders', require('./orders'));
module.exports = router;
./routes/orders.js
const express = require('express');
const router = express.Router();
const io = require('../index');
io.on('connection', (client) => {
console.log("CLIENT CONNECTED");
})
router.get(... etc etc
I expect to get a connection console but instead I'm getting an error that IO is not a function. When I console.log(io) I get {}
Try this way
const user = require('{SET FILE PATH}');
io.on('connection', function (socket) {
console.log('Socket connected...', socket.id);
socket.on('login', function (req) {
user.login(socket, req, 'login'); // socketObj , req , methodName
})
});
user.js
class User {
login(socket, req, methodName) {
console.log("Socket ref is ::: " , socket);
}
}
module.exports = new User();

Pass Soket.io to Express routes

I would use socket.io in my routes file.
I have found multiple methods but no one worked for me.
Now I'm trying this solution
var http = require("http");
var admin = require('firebase-admin');
var firebase = require("firebase");
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var port = process.env.app_port || 8080; // set our port
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var server = app.listen(port);
var io = require("socket.io")(server);
var routerProj = require("./routes/routes")(io);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,*");
next();
});
var config = {
XXX
};
firebase.initializeApp(config);
var serviceAccount = require("./ServiceAcountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://datatable-18f93.firebaseio.com"
});
app.use("/v1", routerProj);
//Create HTTP server and listen on port 8000 for requests
// Print URL for accessing server
console.log("Server running at http://127.0.0.1:8080/");
io.sockets.on("connection", function (socket) {
console.log("a user is connected");
});
Routes.js
var express = require("express"); // call express
var router = express.Router(); // get an instance of the express Router
var admin = require("firebase-admin");
module.exports = function (io) {
/*router.use(function (req, res, next) {
// do logging
io.on('connection', function (socket) {
console.log('User has connected to Index');
});
});*/
router.use(function (req, res, next) {
io.on('save-message', function (socket) {
console.log('User has connected to Index');
});
});
router
.route("/")
.get(function (req, res, err) {
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.once("value", function (snapshot) {
var list = [];
snapshot.forEach(function (elem) {
list.push(elem.val());
})
list = JSON.stringify(list);
//list = JSON.parse(list)
//console.log(JSON.stringify(list))
res.send(list);
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
res.status(500).send(errorObject.code);
});
});
router
.route("/")
.post(function (req, res, err) {
console.log(req.body);
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.push(
{
"text": req.body.text
}
);
});
return router
}
sockets are working in my server.js file , in console I get the message :"a user is connected" when I run my angular app.
But in my browser I run http://127.0.0.1:8080/v1in router.js console.log is not working, so sockets is not getting passed.
I have tried to emit an event :
ngOnInit() {
this.socket.emit('save-message', { room: "hello" });
}
In my router.js :
router.use(function (req, res, next) {
io.on('save-message', function (socket) {
console.log('User has connected to Index');
});
});
console.log don't print anything.

Categories