UserId undefined-socket io /node js - node.js

I'm trying to use socket.io for a while but I faced some problem in emit data to client side
the code works perfectly but I keep getting not defined for userId on the client side see below
server.js
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const { v4: uuidv4 } = require('uuid');
app.set('view engine', 'ejs')
app.use(express.static('public'))
app.get('/', (req, res) => {
res.redirect(`/${uuidv4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
})
io.on('connection', socket => {
socket.on('join-room', (roomId, userId) => {
console.log(roomId, userId)
socket.join(roomId)
socket.to(roomId).broadcast.emit('connect', userId)
console.log(userId)
})
})
server.listen(3000)
client
const socket = io('/')
const $events = document.getElementById('events');
const newItem = (content) => {
const item = document.createElement('li');
item.innerText = content;
return item;
};
socket.emit('join-room', ROOM_ID, 10) // 10 here is the userId
socket.on('connect', function(userId) {
$events.appendChild(newItem('user connected:' + userId)); // the userId ==== undefined
})
the is the error

Update your server file like shown below
io.on('connection', socket => {
socket.on('join-room', (roomId, userId) => {
console.log(roomId, userId)
socket.join(roomId)
socket.to(roomId).emit('connect', userId)
console.log(userId)
})
})

Related

My socket event don't trigger when I am emit it in Nodejs

My socket event doesn't trigger when I emit it in Nodejs, I know it because I don't see "Pizza" in my console.
This is my code:
const express = require("express");
const cors = require("cors");
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server, {
});
app.use((req, res, next) => {
req.io = io;
next()
})
app.use(cors());
io.on('connection', (socket) => {
socket.on("dummy_event", (data) => {
console.log(`Socket 🍕`); // I don't see this message in my console
if(!data.name) return;
})
});
app.get("/socket_test", (req, res) => {
req.io.emit("dummy_event", {name: "pizza"})
return res.json({data: 'dummy text'})
})
server.listen(4000, () => {
console.log(`Server Started on Port 4000`);
})

Socketio undefined results

a few days ago I tried to train with react by creating a real-time chat application, but I'm a bit lost in the io socket, I can't send a message or notification on a specific user, I get an "undefined" error, here is my socket io code:
I tried to retrieve the user with the id as receiverId but socket io returns me undefined
about this function:
socket.on("friendRequest", ({ senderId, receiverId }) => { const receiver = getUser(receiverId); console.log(receiver) });
How can I fix this error,
thank you very much
And sorry for my English,
const express = require('express');
const socketio = require('socket.io');
const http = require('http');
const cors = require('cors');
const PORT = process.env.PORT || 5000;
const router = require('./router');
//const { Socket } = require('dgram');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
app.use(router);
app.use(cors());
let users = [];
const addUser = (userId, socketId) => {
!users.some((user) => user.userId === userId) &&
users.push({ userId, socketId });
};
const removeUser = (socketId) => {
users = users.filter((user) => user.socketId !== socketId);
};
const getUser = (userId) => {
return users.find((user) => user.userId === userId);
};
io.on('connect', (socket) => {
console.log("a user connected.");
socket.on("addUser", (userId) => {
addUser(userId, socket.id);
io.emit("getUsers", users);
});
socket.on("sendNotification", ({ senderId, receiverId, type }) => {
const receiver = getUser(receiverId);
io.to(receiver.socketId).emit("getNotification", {
senderId,
type,
});
});
socket.on("friendRequest", ({ senderId, receiverId }) => {
const receiver = getUser(receiverId);
console.log(receiver)
});
socket.on("sendText", ({ senderId, receiverId, text }) => {
const receiver = getUser(receiverId);
io.to(receiver.socketId).emit("getText", {
senderId,
text,
});
})
socket.on("disconnect", () => {
console.log("User Disconnected", socket.id);
removeUser(socket.id);
io.emit("getUsers", users);
});
});
app.use(router);
server.listen(PORT,() => console.log('Server has started on port ${PORT}'));```

Chai testing TypeError: Converting circular structure to JSON

I'm a new learner express.js I want to test simple post and get operations with tdd mechanism. I created the test, route, index and db files but when I try to test POST method it gives me this error.
This is my routes/task.js
const express = require('express');
const router = express.Router();
router.post("/api/task", async (req,res) => {
try {
const task = await new Task(req.body).save();
res.send(task);
} catch (error) {
res.send(error);
}
})
This is my test/task.js
let chai = require("chai");
const chaiHttp = require("chai-http");
const { send } = require("process");
let server = require("../index");
//Assertion Style
chai.should();
chai.use(chaiHttp);
describe('Tasks API', () => {
/**
* Test the POST Route
*/
describe('POST /api/task', () => {
it("It should POST a new task", () => {
const task = {task: "Wake Up"};
chai.request(server)
.post("/api/task")
.send(task)
.end((err, response) => {
response.should.have.status(201);
response.body.should.be.a('string');
response.body.should.have.property('id');
response.body.should.have.property('task');
response.body.should.have.property('task').eq("Wake Up");
response.body.length.should.be.eq(1);
done();
});
});
});
});
This is my db.js
var sqlite3 = require('sqlite3').verbose()
const DBSOURCE = "db.sqlite"
let db = new sqlite3.Database(DBSOURCE, (err) => {
if (err) {
// Cannot open database
console.error(err.message)
throw err
}else{
console.log('Connected to the SQLite database.')
db.run(`CREATE TABLE IF NOT EXISTS todo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task text
)`,
(err) => {
if (err) {
// Table already created
console.log(err);
}
});
}
});
module.exports = db
And this is my index.js
const connection = require('./db');
const express = require('express');
const app = express();
const cors = require("cors");
const port = process.env.PORT || 8080;
app.use(express.json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World');
});
app.post('/api/task', (req, res) => {
res.status(201).send(req);
});
app.listen(port, () => console.log(`Listening on port ${port}...`));
module.exports = app;
The thing that I try to do is building a test case to test the post method. I think I couldn't built the correct relations the files.
Currently, just by doing a POST request to /api/task, the error will appear. That is because of these lines in index.js:
app.post('/api/task', (req, res) => {
res.status(201).send(req);
});
The req parameter is circular, hence cannot be JSON-stringified.
Solution
In routes/task.js export the router:
const express = require('express');
const router = express.Router();
router.post("/api/task", async (req,res) => {
try {
const task = await new Task(req.body).save();
res.send(task);
} catch (error) {
res.send(error);
}
})
// By adding this line you can export the router
module.exports = router
In index.js, include the routes/task.js file and pass it to app.use(...), also remove the now-obsolete /api/task route:
const connection = require('./db');
const express = require('express');
const app = express();
const cors = require("cors");
const taskRoutes = require("./routes/task")
const port = process.env.PORT || 8080;
app.use(express.json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World');
});
app.use(taskRoutes)
app.listen(port, () => console.log(`Listening on port ${port}...`));
module.exports = app;
This way we got rid of the circular structure stringifying and the tests should now pass.

WebSocket (Socket.io) connection Error - failed: Connection closed before receiving a handshake response

I have spent all day figuring out and searching for solution online for error
WebSocket connection to 'wss://localhost/myapp/peerjs?key=peerjs&id=5c70da87-62c1-41dd-b1b1-e7aea5acc09b&token=j4n0nprnu6' failed: Connection closed before receiving a handshake response
I am developing this nodejs app on express server. My express server where I initialize PeerServer along with it:
// Dependencies
const express = require('express')
const app = express()
const httpPort = process.env.PORT || 80
const httpsPort = 443
const { ExpressPeerServer } = require('peer')
const path = require('path')
const http = require('http')
const https = require('https')
const fs = require('fs')
// Certificate & credentials
const privateKey = fs.readFileSync(path.join(__dirname, 'certs', 'key.pem'))
const certificate = fs.readFileSync(path.join(__dirname, 'certs', 'cert.pem'))
const credentials = {
key: privateKey,
cert: certificate
}
const mainServer = http.createServer(app).listen(httpPort, () => { console.log('Main Server listening to port ' + httpPort) })
const httpsServer = https.createServer(credentials, app).listen(httpsPort, () => { console.log('Peer Server listening to port ' + httpsPort) })
const peerServer = ExpressPeerServer(mainServer, {
debug: true,
path: '/myapp'
})
//app.use('peerjs', peerServer)
app.use(peerServer)
const io = require('socket.io')(httpsServer)
const { v4: uuidV4 } = require('uuid')
app.set('view engine', 'ejs')
app.use(express.static('public'))
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
//console.log('Room Created / Joined')
})
io.on('connection', (socket) => {
//console.log('IO Connectedd')
socket.on('join-room', (roomId, userId) => {
console.log(roomId, userId)
socket.join(roomId)
socket.to(roomId).emit('user-connected', userId)
socket.on('disconnect', () => {
socket.to(roomId).emit('user-disconnected', userId)
})
})
})
And below is my client side code
const socket = io('/')
const videoGrid = document.getElementById('video-grid')
const myPeer = new Peer(undefined, {
host: '/',
port: '443',
path: '/myapp'
})
const ownVideo = document.createElement('video') // Own Video
ownVideo.muted = true
const peers = {}
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
addVideoStream(ownVideo, stream)
myPeer.on('call', call => { // On Receiving Other Persons Call
call.answer(stream) // Send Video Stream On Answer
const video = document.createElement('video')
call.on('stream', userVideoStream => { // Send Back Video Stream On Stream
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected', userId => { // Allow Self To Be Connected To Others
console.log('User Connected: ' + userId)
connectToNewUser(userId, stream)
})
})
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
myPeer.on('open', id => {
socket.emit('join-room', ROOM_ID, id)
})
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream) // We Connect To Other User
const video = document.createElement('video')
call.on('stream', userVideoStream => { // Other User Connects To Us
addVideoStream(video, userVideoStream)
})
call.on('close', () => { // Other User Disconnects
video.remove()
})
peers[userId] = call
}
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
I am new to nodejs and couldn't find any solution online for it.
Please help!!
Your code needed some rearrangement, once done, it worked fine for me on W10, VSC and Chrome Version 91.0.4472.164 (Official Build) (64-bit). It is simpler to include my working code rather than trying to explain each change. I will include here the script.js and server.js files (working) and the whole code working workspace in github here for anybody to use. I want to emphasize that you do want to call the peer.on('call'.... event handler ahead of waiting for any promises, to make sure your remote client has this handler ready before receiving a call from the originator client, that was not part of the issue that created the error you asked about.
CLIENT SIDE:
const socket = io('/')
const videoGrid = document.getElementById('video-grid')
let Peer = window.Peer;
const peer = new Peer({
host: '/',
path: '/peerjs',
debug: 3,
port: 80,
secure: false,
});
console.log('***Created peer instance, userId: ' + peer.id)
// Function to obtain stream and then await until after it is obtained to go into video chat call and answer code. Critical to start the event listener ahead of everything to ensure not to miss an incoming call.
const ownVideo = document.createElement('video') // Own Video
ownVideo.muted = true
const peers = {}
// On Receiving Other Persons Call
peer.on("call", async (call) => {
try {
let stream = null;
stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
call.answer(stream) // Send Video Stream On Answer
const video = document.createElement('video');
// Send Back Video Stream On Stream
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream);
});
}
catch (err) {
/* handle the error */
console.log('*** ERROR returning the stream: ' + err);
}
});
(async () => {
try {
let stream = null;
stream = await navigator.mediaDevices.getUserMedia(
{
audio: true,
video: true,
});
if (stream != undefined) {
addVideoStream(ownVideo, stream);
console.log('added own Video stream');
} else {
console.log('You can only access your audio/video media streams over https');
alert('Sorry retry using https, for security reasons Google Media blocks access to your video stream over unsecure http connections');
}
} catch (err) {
/* handle the error */
console.log('*** ERROR returning the stream: ' + err);
alert('Sorry retry using https, for security reasons Google Media blocks access to your video stream over unsecure http connections');
}
})();
socket.on('user-connected', userId => { // Allow Self To Be Connected To Others
console.log('User Connected: ' + userId)
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
connectToNewUser(userId, stream)
})
})
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
peer.on('open', id => {
socket.emit('join-room', ROOM_ID, id)
})
function connectToNewUser(userId, stream) {
const call = peer.call(userId, stream) // We Connect To Other User
const video = document.createElement('video')
call.on('stream', userVideoStream => { // Other User Connects To Us
addVideoStream(video, userVideoStream)
})
call.on('close', () => { // Other User Disconnects
video.remove()
})
peers[userId] = call
}
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
SERVER SIDE:
// Dependencies
const express = require('express')
const app = express()
const httpPort = process.env.PORT || 80
const httpsPort = 443
const { ExpressPeerServer } = require('peer')
const path = require('path')
const http = require('http')
const https = require('https')
const fs = require('fs')
const certs = `C:/Users/spine/Documents/Personal Files/ArduinoData/packages/esp8266/hardware/esp8266/2.7.4/libraries/ESP8266WiFi/examples/BearSSL_Server/`
// Certificate & credentials
const privateKey = fs.readFileSync(path.join(certs, 'key.pem'))
const certificate = fs.readFileSync(path.join(certs, 'cert.pem'))
const credentials = {
key: privateKey,
cert: certificate
}
const mainServer = http.createServer(app).listen(httpPort, () => { console.log('Main Server listening to port ' + httpPort) })
const httpsServer = https.createServer(credentials, app).listen(httpsPort, () => { console.log('Peer Server listening to port ' + httpsPort) })
const peerServer = ExpressPeerServer(mainServer, {
debug: true,
ssl: {},
})
app.use('/peerjs', peerServer)
// app.use(peerServer)
const io = require('socket.io')(httpsServer,{
// const io = require('socket.io')(mainServer, {
cors: {
origin: "*",
},
});
const { v4: uuidV4 } = require('uuid')
app.set('view engine', 'ejs')
app.use(express.static('public'))
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
//console.log('Room Created / Joined')
})
io.on('connection', (socket) => {
//console.log('IO Connectedd')
socket.on('join-room', (roomId, userId) => {
console.log(roomId, userId)
socket.join(roomId)
socket.to(roomId).emit('user-connected', userId)
socket.on('disconnect', () => {
socket.to(roomId).emit('user-disconnected', userId)
})
})
})
I got it working with following cod on server side. Though I was able to get it work over SSL only.
const express = require('express')
const app = express()
const httpPort = process.env.PORT || 80
const httpsPort = 443
const { ExpressPeerServer } = require('peer')
const path = require('path')
const http = require('http')
const https = require('https')
const fs = require('fs')
// Certificate & credentials
const privateKey = fs.readFileSync(path.join(__dirname, 'certs', 'key.pem'))
const certificate = fs.readFileSync(path.join(__dirname, 'certs', 'cert.pem'))
const credentials = {
key: privateKey,
cert: certificate
}
const httpsServer = https.createServer(credentials, app).listen(httpsPort, () => { console.log('Peer Server listening to port ' + httpsPort) })
const peerServer = ExpressPeerServer(httpsServer, {
debug: true,
path: '/myapp'
})
app.use(peerServer)
const io = require('socket.io')(httpsServer, {
forceNew: true,
transports: ["polling"],
})
const { v4: uuidV4 } = require('uuid')
app.set('view engine', 'ejs')
app.use(express.static('public'))
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
})
io.on('connection', (socket) => {
socket.on('join-room', (roomId, userId) => {
socket.join(roomId)
socket.broadcast.to(roomId).emit('user-connected', userId)
socket.on('disconnect', () => {
socket.broadcast.to(roomId).emit('user-disconnected', userId)
})
socket.on('text-message', message => {
socket.broadcast.to(roomId).emit('text-message-received', message)
})
socket.on('system-stream-updated', remoteUserId => {
socket.broadcast.to(roomId).emit('new-remote-stream', remoteUserId)
})
})
})

peerjs event 'call' some times not fire up

I setup my local server.
const fs = require('fs');
const {PeerServer} = require('peer');
const peerServer = PeerServer({
port: 3001,
debug: false,
secure: true,
path: '/',
ssl: {
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem')
}
});
peerServer.on('connection', (_client) => {
console.log('Client connects');
});
peerServer.on('disconnect', (_client) => {
console.log('Client disconnects');
});
I use also local express server
const fs = require('fs');
const key = fs.readFileSync('./key.pem');
const cert = fs.readFileSync('./cert.pem');
const express = require('express');
const app = express();
const server = require('https').createServer({key: key, cert: cert },app);
const io = require('socket.io')(server);
const {v4: uuid} = require('uuid');
require('./room')(io)
server.listen(3000,'192.168.1.30');
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.get('/', ((req, res) => {
res.redirect(`${uuid()}`)
}))
app.get('/:room', ((req, res) => {
res.render('room', {roomId: req.params.room})
}))
function socketInit(io) {
io.on('connection', socket => {
socket.on('join-room', (roomId, userId) => {
socket.join(roomId)
socket.to(roomId).broadcast.emit('user-connected', userId)
socket.on('user_disable_camera', (userId) => {
socket.to(roomId).broadcast.emit('user_disable_camera', userId)
});
socket.on('user_enable_camera', (userId) => {
socket.to(roomId).broadcast.emit('user_enable_camera', userId)
})
// socket.on('screen_share_start', (userId) => {
// socket.to(roomId).broadcast.emit('user-disconnected', userId)
// });
socket.on('screen_share_stop', (userId) => {
socket.to(roomId).broadcast.emit('screen_share_stop', userId)
});
socket.on('disconnect', () => {
socket.to(roomId).broadcast.emit('user-disconnected', userId)
})
})
});
}
module.exports = socketInit
In my html file
const myPeer = new Peer(undefined, {
host: '/',
path: '/',
secure: true,
port: '3001'
});
myPeer.on('error', e => {
console.log('my peer error', e);
myPeer.reconnect();
})
...grab media stream...
addVideo(document.getElementById('me'), myVideo, stream);
myPeer.on('call', call => {
call.answer(stream);
peers[call.peer] = call;
console.log('call', call);
const video = document.createElement('video');
video.id = call.peer;
call.on('stream', userVideoStream => {
addVideo(videoList, video, userVideoStream)
});
})
socket.on('user-connected', userId => {
console.log('user conected', userId);
connectToNewUser(userId, stream);
})
function connectToNewUser(userId, stream) {
try {
const call = myPeer.call(userId, stream);
peers[userId] = call
console.log('connectToNewUser', stream, userId, peers, call);
const video = document.createElement('video');
video.id = userId;
call.on('stream', videoStream => {
addVideo(videoList, video, videoStream)
});
call.on('close', () => {
video.remove();
});
} catch (e) {
console.log('errrrrrrrrr', e);
}
}
Some times when i connect my computer and other computer same network, and https is present myPeer.on('call'... not fire up (2 users). When I open new tab(must be at least 3 users) with same room Id it some times is been called and then video is showing properly. Can some one point me in direction were is error ?

Resources