I am using socket.io to connect to a different domain, and it can successfully connect using polling, however when attempting to connect using websockets gets the error "WebSocket connection to 'wss://XXXXX' failed".
After observing the network activity the server seems to indicate that it is capable of upgrading to a websocket connection (although I won't claim to be an expert in understanding these requests), but isn't able to do so:
I'm just trying to produce a minimal viable product right now so here is my node.js server code:
let http = require('http');
let https = require('https');
let fs = require('fs');
let express = require('express');
const privateKey = fs.readFileSync('XXXXXXXXX', 'utf8');
const certificate = fs.readFileSync('XXXXXXXXX', 'utf8');
const ca = fs.readFileSync('XXXXXXXXX', 'utf8');
const options = {
key: privateKey,
cert: certificate,
ca: ca
};
let app = express();
let httpsServer = https.createServer(options,app);
let io = require('socket.io')(httpsServer, {
cors: {
origin: true
}
});
httpsServer.listen(443);
console.log('starting');
io.sockets.on('connection', (socket) => {
console.log("something is happening right now")
socket.on("salutations", data => {
console.log(`you are now connected via ${socket.conn.transport.name}`);
socket.emit("greetings", "I am the socket confirming that we are now connected");
});
});
Client-side JavaScript:
const socket = io("https://XXXXXXX");
console.log(socket);
socket.on("connect", () => {
console.log("now connected");
socket.on("message", data => {
console.log(data);
});
socket.on("greetings", (elem) => {
console.log(elem);
});
});
let h1 = document.querySelector('h1');
h1.addEventListener('click',()=>{
console.log("I am now doing something");
socket.emit("salutations", "Hello!");
})
The only suggestion in the official documentation for this issue isn't relevant because I'm not using a proxy, and other suggested fixes result in no connection at all (presumably because they prevent it from falling back to polling)
EDIT: also if it helps narrow down the problem, when querying my server using https://www.piesocket.com/websocket-tester it results in "Connection failed, see your browser's developer console for reason and error code"
Related
I am trying to connect socket.io client which inside react app to the socket.io server but i am getting xhr poll error. I am unable to figure out what is going wrong? client & server code is as follow:
import io from 'socket.io-client';
const socket = io("ws://loacalhost:5000");
socket.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
});
const express = require('express');
const app = express();
app.use(require('cors')());
const http = require('http');
const server = http.createServer(app);
const io = require("socket.io")(server, {
rejectUnauthorized: false,
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"]
}
})
io.on("connection", (socket) => {
console.log(socket.id)
})
server.listen(5000, () => {
console.log('Server is listening on Port 5000');
});
Everything is ok in server file as well as everything is ok in client file except there is syntax mistake in client code i.e.
const socket = io("ws://loacalhost:5000");
replaced with:
const socket = io("ws://localhost:5000");
then it is worked fine, successfully connected to server
Your localhost spelling is incorrect.
const socket = io("ws://loacalhost:5000");
Replaced with
const socket = io("ws://localhost:5000");
I'm creating my product and stuck with this problem. One day I setuped socket.io and everything worked well. On the next day I migrate my server and client from http to https. After the migration client side and server side still connected, but I can't emit from client side to server and from server to client.
Server side
I have my ssl certificate inside ./security/cert.key and ./security/cert.pem they are loading correctly. My server running on https://localhost:5000
import fs from "fs";
import https from "https";
import socketio from "socket.io";
import express from "express";
// HTTPS optiosn
const httpsOptions = {
key: fs.readFileSync("./security/cert.key"),
cert: fs.readFileSync("./security/cert.pem"),
};
// Setup express and https server
const app = express();
const server = https.createServer(httpsOptions, app);
// Setup socket io
const io = socketio.listen(server, {
origins: "https://localhost:3000",
transports: ["websocket"],
});
server.listen(5000, () => {
console.log(`server listening on https://localhost:5000`);
});
io.listen(server);
io.on("connection", (socket) => {
console.log("new socket connected!");
console.log(`data = ${socket.handshake.query.data}`);
socket.emit("some-event");
socket.on("some-event-2", () => console.log("some-event-2 happened!"));
});
Client Side
My example react component. My react app is running on https://localhost:3000. HTTPS is connected and working well.
import React from "react";
import io from "socket.io-client";
const Sandbox: React.FC = () => {
const query = {
"data": 123,
};
const socket = io.connect("https://localhost:5000", {
secure: true,
query,
transports: ["websocket"],
});
socket.on("connect", () => console.log("connect!"));
socket.on("some-event", () => console.log("some event happened"));
socket.emit("some-event-2");
return <React.Fragment />;
};
export default Sandbox;
And now the problem. On client side in console I should see connect! and some event happened
And on server side I should see the messages new socket connected! and data = 123, some-event-2 happened!. But instead my client side console is completely clear
And server side console have only a few logs, but dont contains emit logs
What should I do? Maybe I'm incorrectly using socket.io with https?
I fixed my error.
The problem was that I was firstly create https server and after that only call .listen() on it. listen() - is not a void, it's return another server obj. You need to pass the result of .listen() function inside your io.listen()
// Don't do that❌
var server = https.createServer(options, app);
server.listen(5000);
io.listen(server);
// Do that✅
var server = https.createServer(options, app).listen(5000);
io.listen(server);
I'm starting to use socket.io and I have a problem that I can't solve so far
I have two nodejs running, one is the socket.io data server and the other one is going to interact with web clients
I need to get data from the server and send it to my web clients, the problem is I can't emit data to the clients outside the 'on connect'
I think is better to explain it with a simple example
const socket = require('socket.io-client')('http://localhost:12000');
const SocketIO = require('socket.io');
const app = require('../app');
const server = http.createServer(app);
server.listen(port);
// client socket, this is a regular message from
// the server running on port 12000, it works
socket.on('msg_from_server', data => {
console.log(data);
});
// server socket
const io = SocketIO(server);
io.on('connection', (s) => {
// this works
s.emit('msg_to_client', {data: 'xxxx'})
// this doesn't works
socket.on('msg_from_server', data => {
console.log(data);
});
});
socket client for server on port 12000 and socket from io.on('connection', (socket) both are different. But you are mixing them both.Do something like this:
const Socket_12000 = require('socket.io-client')('http://localhost:12000');
const SocketIO = require('socket.io');
const app = require('../app');
const server = http.createServer(app);
server.listen(port);
// client socket
socket.on('msg_from_server', data => {
console.log(data);
});
// server socket
const io = SocketIO(server);
io.on('connection', (socket) => {
// this works
socket.emit('msg_to_client', {data: 'xxxx'})
// this doesn't works
Socket_12000.on('msg_from_server', data => {
console.log(data);
});
});
I have created a basic gist depicting the problem/solution please commant if you are looking something else.
https://gist.github.com/sandeepp2016/bb1946bcbeb2f11d57bc3aa2e44c158e
Here is my code:
var socket = require('socket.io-client')('http://127.0.0.1:3000/printers', {
query: "shop=" + "123456",
transports: ["websocket"]
});
If I delete query, I can connect to socket. Where am I wrong?
There doesn't seem to be anything wrong with your client-side code. I can connect by copying and pasting your code.
I suspect the problem is within your server-side code. Here is an example I am using with your client-side code:
var http = require('http');
var io = require('socket.io');
var server = http.createServer(function(req,res){
res.writeHead(200);
res.end('Hello, World!\n');
});
server.listen(80);
var socket = io.listen(server);
socket.use(function(socket, next){
console.log("Query: ", socket.handshake.query);
if (socket.handshake.query.shop == '123456') {
next();
}
next(new Error('You cannot use that shop'));
});
socket.on('connection', function(client) {
console.log('New Connection');
});
I'm able to obtain the query data in the 'socket.use' function. If I don't call the next() function, the client will never get the message that the server has received the response and is connected.
I recommend checking out the example used in this thread.
I have the current setup:
Nodejs Proxy (running http-reverse-proxy) running on port 80.
Rails server running on port 3000
Nodejs web server running on port 8888
So any request starting with /nodejs/ will be redirected to nodejs web server on 8888.
Anything else will be redirected to the rails server on port 3000.
Currently Socket.io requires a connection url for io.connect.
Note that /nodejs/socket.io/socket.io.js is valid and returns the required socket.io client js library.
However, I am not able to specify connection_url to /nodejs/ on my server.
I have tried http://myapp.com/nodejs and other variants but I am still getting a 404 error with the following url http://myapp/socket.io/1/?t=1331851089106
Is it possible to tell io.connect to prefix each connection url with /nodejs/ ?
As of Socket.io version 1, resource has been replaced by path. Use :
var socket = io('http://localhost', {path: '/nodejs/socket.io'});
See: http://blog.seafuj.com/migrating-to-socketio-1-0
you can specify resource like this:
var socket = io.connect('http://localhost', {resource: 'nodejs'});
by default resource = "socket.io"
If you are using express with nodejs:
Server side:
var io = require('socket.io')(server, {path: '/octagon/socket.io'});
then
io.on('connection', function(socket) {
console.log('a user connected, id ' + socket.id);
socket.on('disconnect', function() {
console.log('a user disconnected, id ' + socket.id);
})
})
socket.on('publish message ' + clientId, function(msg) {
console.log('got message')
})
Client side:
var socket = io('https://dev.octagon.com:8443', {path: '/octagon/socket.io'})
then
socket.emit('publish message ' + clientId, msg)
I use below approach to achieve this goal:
client side:
var socket = io.connect('http://localhost:8183/?clientId='+clientId,{"force new connection":true});
server side:
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(socket) {
console.log("url"+socket.handshake.url);
clientId=socket.handshake.query.clientId;
console.log("connected clientId:"+clientId);
});
reference:https://github.com/LearnBoost/socket.io/wiki/Authorizing#global-authorization
If you are serving your app with express, then maybe you can check this out. Remember express uses http to serve your application.
const express = require('express'),
http = require('http'),
socketIo = require('socket.io'),
app = express()
var server = http.createServer(app);
var io = socketIo(server);
io.on('connection', (socket)=>{
// run your code here
})
server.listen(process.env.PORT, ()=> {
console.log('chat-app inintated succesfully')
})