running into this error with socket.io + nextjs + custom express server:
WebSocket connection to 'ws://localhost:3000/socket.io/?EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established.
Server:
const { Server, Socket } = require("socket.io");
const express = require("express");
const { createServer } = require("http");
const next = require("next");
const { parse } = require("url");
const dev = process.env.NODE_ENV !== "production";
const PORT = process.env.PORT || 3000;
const user = require("./server/api/userAPI");
const game = require("./server/api/gameAPI");
const app = next({ dev });
const handle = app.getRequestHandler();
console.log("hello");
app
.prepare()
.then(() => {
const expressApp = express();
const httpServer = createServer(expressApp);
const io = new Server(httpServer, { transports: ["websocket"] });
expressApp.use(express.json());
expressApp.use("/user", user);
expressApp.use("/game", game);
expressApp.listen(3000, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
expressApp.get("*", (req, res) => {
return handle(req, res);
});
io.on("connect", () => {
console.log("socket connected");
const count = io.engine.clientsCount;
console.log(count);
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
here is the client:
useEffect(() => {
const socket = io("http://localhost:3000", {
// reconnectionDelay: 1000,
reconnection: true,
reconnectionAttempts: 10,
transports: ["websocket"],
agent: false,
upgrade: false,
rejectUnauthorized: false,
});
socket.on("connect", () => {
console.log("someone connected: ", socket?.id);
});
}, []);
never worked with websockets or a custom next server before, found this online which is similar to my issue but no luck: https://github.com/vercel/next.js/issues/30491
how can i get the socket to connect?
Related
i'm developing a chat app in express by socket.io and this is my code:
well the front end cannot connect to socket io but server is running and i can login
const express = require("express");
const { Server } = require("socket.io");
const helmet = require("helmet");
const cors = require("cors");
const authRouter = require("./routes/authRouter");
const { corsConfig } = require("./controllers/serverController");
const {
Authorization,
AddFriend,
Disconnect,
dm,
} = require("./controllers/socketController");
require("dotenv").config();
const app = express();
const server = require("http").createServer(app);
const io = new Server(server, {
cors: corsConfig,
});
app.use(helmet());
app.use(cors(corsConfig));
app.use(express.json());
//! Routes
app.use("/auth", authRouter);
app.get("/", (req, res) => res.send("Hi"));
io.use(Authorization);
io.on("connection", (socket) => {
console.log("socket")
socket.on("add_friend", (friendName, cb) => {
AddFriend(socket, friendName, cb);
});
socket.on("disconnect", Disconnect);
socket.on("dm", (message) => dm(socket, message));
});
server.listen(5050, () => {
console.log(app.get("env"));
});
but my server isnt running on localhost:5050 this is the error i got :
curl "http://localhost:5050/socket.io/?EIO=4&transport=polling" curl: (7) Failed to connect to localhost port 5050: Connection refused
ive tried to change config of socket server but none of those worked
i have a socketjs file which will create my config and a useEffect hook which inside that ive tried to connect to my server
frontendCode:
socket.js
import { io } from "socket.io-client";
const socket = (user) =>
new io("http://localhost:5050", {
autoConnect: false,
withCredentials: true,
auth: {
token: user.token,
},
});
export default socket;
useSocket.js:
socket.connect();
socket.on("friends", (FriendList) => {
setFriendList(FriendList);
});
socket.on("messages", (messages) => {
setMessages(messages);
});
socket.on("dm", (message) => {
setMessages((prev) => [message, ...prev]);
});
socket.on("connected", (status, username) => {
setFriendList((prev) => {
const friends = [...prev];
return friends.map((friend) => {
if (friend.username === username) {
friend.status = status;
}
return friend;
});
});
});
socket.on("connect_error", () => {
setUser({ loggedIn: false });
});
returned error from frontend:
Firefox can’t establish a connection to the server at ws://localhost:5050/socket.io/?EIO=4&transport=websocket&sid=1uKM4znamAHH8P6kAAKY.
My frontend service is running on netlify.
And backend is on heroku.
I am trying to make chatApp.
After I entered chatRoom press sending button below error message pop up on console log.
"Failed to execute 'send' on 'WebSocket': Still in CONNECTING state."
I guess
problem is below code.
client
created() {
this.channel = this.$route.query.channel || '';
this.$store.state.user.stateWebSocket = new WebSocket('ws://peaceful-ridge-59102.herokuapp.com:9999/ws');
// this.websocket = new SockJS('http://localhost:8080/ws/realtime');
this.websocket=this.$store.state.user.stateWebSocket;
this.websocket.onmessage = ({ data }) => {
const vo = JSON.parse(data);
if (vo.channel === this.channel) {
this.appendNewMessage(this.tempName, vo.message, vo.time);
}
};
this.websocket.onopen = (event) => {
console.log('open event..', event);
};
this.websocket.onerror = (event) => {
console.log('error', event);
};
this.websocket.onclose = (event) => {
console.log('close', event);
};
}
This is sever.js
const cors = require('cors');
const express = require('express');
const app = express();
const WebSocket = require('ws');
const PORT = 9999;
app.use(
cors({
origin: true,
credentials: true,
})
);
const server = app.listen(PORT, () => {
console.log(PORT, 'waiting unitil connects');
});
app.get('/', (req, res) => {
res.send('Hello World!');
});
const wss = new WebSocket.Server({ server, path: '/ws' });
wss.on('connection', (ws, req) => {
// connection
console.log('새로운 클라이언트 접속');
ws.on('message', (message) => {
// receiving message
const json = JSON.parse(message.toString());
json.time = Date.now()
message = JSON.stringify(json)
console.log(message.toString());
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message.toString());
}
});
// Runs when client disconnects
wss.on('disconnect', () => {
});
});
ws.on('error', (err) => {
// error
console.error(err);
});
ws.on('close', () => {
// close
console.log('Client close');
clearInterval(ws.interval);
});
});
some people say I am sending your message before the WebSocket connection is established.
I am newbie on JS plz help me~!
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)
})
})
})
I am running backend(nodejs server) at port 5000. And running frontend at reactjs.
Peerjs also not connecting. Everytime it throwing
WebSocket connection to
'ws://localhost:5000/socket.io/?EIO=3&transport=websocket&sid=RpMvIyH3kAFbQpntAAAA'
failed: Invalid frame header
I want keep frontend and backend in separate server.
Frontend(React)
try {
socket = io.connect('http://localhost:5000/');
} catch (e) {
console.error(e)
}
BackEnd(Nodejs)
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const { v4: uuidv4 } = require('uuid');
const { ExpressPeerServer } = require('peer');
const PORT = process.env.PORT || 5000;
const peerServer = ExpressPeerServer(server, {
debug: true
});
app.use('/peerjs', peerServer);
io.on('connection', (socket) => {
socket.on('join-room', (roomId, userId) => {
socket.join(roomId);
socket.to(roomId).broadcast.emit('user-connected', userId);
socket.on('message', message => {
io.to(roomId).emit('createMessage', message);
})
socket.on('disconnect', () => {
socket.to(roomId).broadcast.emit('user-disconnected', userId)
})
})
});
server.listen(PORT, () => {
console.log(`Server has started on port ${PORT}`);
});
I'm using socket.io with peerjs to create a video conference app. Everything works fine on localhost. but when i push/host it on heroku it shows me this error in the console of browser :
index.js:83 WebSocket connection to 'wss://vidconsom.herokuapp.com/socket.io/?EIO=3&transport=websocket&sid=zbEGAHBj9w_dpcQfAAAF' failed: Invalid frame header.
Can anyone please help?
UPDATE: CHECK BELOW FOR ANSWER
Here is my server.js code:
const express = require("express");
const app = express();
const path = require("path");
// const { PeerServer } = require("peer");
const { ExpressPeerServer } = require("peer");
const { v4: uuidV4 } = require("uuid");
const server = require("http").Server(app);
const io = require("socket.io")(server);
const PORT = process.env.PORT || 3000;
const expServer = server.listen(PORT, () =>
console.log(`Server started on port ${PORT}`)
);
const peerServer = ExpressPeerServer(expServer, {
path: "/peer",
});
app.set("view engine", "ejs");
app.use(express.static(path.join(__dirname, "/public")));
app.use(peerServer);
app.get("/", (req, res) => {
res.redirect(`/${uuidV4()}`);
});
app.get("/:room", (req, res) => {
res.render("room", {
roomId: req.params.room,
PORT,
host: process.env.host | "/",
});
});
io.on("connection", (socket) => {
socket.on("join-room", (roomId, userId) => {
socket.join(roomId);
socket.to(roomId).broadcast.emit("user-connected", userId);
socket.on("disconnect", () => {
socket.to(roomId).broadcast.emit("user-disconnected", userId);
});
});
});
Here is my frontend script.js code:
const socket = io("/");
const videoGrid = document.getElementById("video-grid");
const myPeer = new Peer(undefined, {
host: "/",
port: PORT,
path: "/peer",
});
const myVideo = document.createElement("video");
myVideo.muted = true;
const peers = {};
navigator.mediaDevices
.getUserMedia({
video: true,
audio: true,
})
.then((stream) => {
addVideoStream(myVideo, stream);
myPeer.on("call", (call) => {
call.answer(stream);
const video = document.createElement("video");
call.on("stream", (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
});
socket.on("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);
const video = document.createElement("video");
call.on("stream", (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
call.on("close", () => {
video.remove();
});
peers[userId] = call;
}
function addVideoStream(video, stream) {
video.srcObject = stream;
video.addEventListener("loadedmetadata", () => {
video.play();
});
videoGrid.append(video);
}
On the frontend script.js use port 443 while deploying to heroku:
const myPeer = new Peer(undefined, {
host: "/",
port: 443,
path: "/peer",
});
server.js file
const express = require("express");
const app = express();
const server = require("http").createServer(app);
const { ExpressPeerServer } = require("peer");
const io = require("socket.io")(server, {
cors: {
origin: "*",
},
});
const peerServer = ExpressPeerServer(server, {
debug: true,
port: 443
});
app.set("view engine", "ejs");
app.use("/peerjs", peerServer);
app.use(express.static(path.join(__dirname, "public")));
app.get("/", (req, res) => {
res.render("home");
});
io.on("connection", (socket) => {
socket.on("event", () => {
// do something
});
socket.on("disconnect", () => {
// do something
});
});
server.listen(process.env.PORT || 3000);
script.js file
const socket = io().connect("/");
let peer = new Peer(undefined, {
path: "/peerjs",
host: "/",
port: 443,
});
You can run express server and ExpressPeerServer on different port. You can find the discussion here https://github.com/peers/peerjs/issues/300.
server.js
//Express Server
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(__dirname+'/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,userName) => {
// Do something
});
});
server.listen(3000);
// Peer Server
var ExpressPeerServer = require('peer').ExpressPeerServer;
var peerExpress = require('express');
var peerApp = peerExpress();
var peerServer = require('http').createServer(peerApp);
var options = { debug: true }
var peerPort = 3001;
peerApp.use('/peerjs', ExpressPeerServer(peerServer, options));
peerServer.listen(peerPort);
client.js
var peer = new Peer(undefined, {
path: "/peerjs",
host: "/",
port: "3001",
config: {'iceServers': [
{ url: 'stun:stun.l.google.com:19302' }
]}
});
maybe you need to add the allowEIO3 option when creating the io server
import { Server } from 'socket.io';
const io = new Server(server, {
allowEIO3: true
});
reference: https://socket.io/docs/v3/troubleshooting-connection-issues/
use either socket io or peer server on different port something like
io.listen(4000);