As the title says I'm trying to connect to a website their WebSocket to get live updates. However I've tried everything, and all it does is the WebSocket immediately disconnects after connecting. I've checked their version of the connection to the WebSocket, they do not reply with anything after the onopen event. I've tried setting the origin in case of them not accepting any connections from origins other than their own.
I'm trying to do this within NodeJS with the ws module. I'm trying to reach the WebSocket of https://rollbit.com (wss://ws.rollbit.com/);
Code
const WebSocket = require('ws');
const ws = new WebSocket('wss://ws.rollbit.com/', {
origin: 'https://rollbit.com'
});
ws.on('open', function open() {
console.log('connected');
});
ws.on('close', function close() {
console.log('disconnected');
});
I've also attempted to do this from within the browser, it works perfectly when I do it from the console when being on their site, when changing to another site and running the code there - it fails. I've tried cookies as well..
Result
connected
disconnected
Any ideas of what I'm missing here?
Related
We currently have a Laravel CMS server that sends a request to another Laravel websocket server which then broadcasts to multiple IoT devices listening on their individual channels for requests. Everything works perfectly.
So it looks like this:
CMS server -> Socket server -> devices
I am trying to initiate these websocket requests from a third server which is not running Laravel, it's just running core PHP and JavaScript. I looked in my browser's Network tab to spy on the websocket connection from a legitimate request, copied it exactly, the connection and subscription succeed but when I send the requests over the socket from my test script, nothing happens. It's literally the exact same socket request over the same channel on the same connection, just with a different socket ID. How could this fail?
I thought maybe it was only accepting requests from that specific server so I copied my test script to that server and still no response. I don't know much about web sockets, could someone please help me understand how I can spoof these messages without using Laravel?
If you're wondering what I'm actually up to, we're decommissioning this CMS server for our new CMS we built in core PHP so we no longer have Laravel as an option but I don't want to rewrite the socket server which uses Laravel, that can stay. I just need to interface with it any way possible. I have full SSH and DNS access to anything I need to configure.
Here is my test script, I've tried about 50 of them I found on Google, none of them give me a response from my specific socket server, besides the connection successful and subscription successful responses.
<script>
let socket = new WebSocket('wss://subdomain.domain.ca:6001/app/apikeyyyyy?protocol=7&client=js&version=4.4.0&flash=false');
var message = {
channel:"aaaaaa.bbbbbbbb",
event:"1000",
data:"{\"channelName\":\"aaaaaa.bbbbbbbb\",\"message\":{\"msgId\":\"\",\"cmd\":\"help\",\"timestamp\":1663616905529,\"request_id\":\"\",\"device_id\":\"\"},event:\"1000\",timestamp:1663616905529,request_id:\"\",device_id:\"\"}"
};
socket.onopen = function(e) {
var data_json = {
event:'pusher:subscribe',
data:{
channel:'aaaaaa.bbbbbbbb',
}
};
socket.send(JSON.stringify(data_json));
socket.send(JSON.stringify(message));
};
socket.onmessage = function(event) {
console.log("Response: " + event.data);
};
socket.onclose = function(event) {
if (event.wasClean) {
alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
// e.g. server process killed or network down
// event.code is usually 1006 in this case
alert('[close] Connection died');
}
};
socket.onerror = function(error) {
alert(`[error] ${error.message}`)
};
</script>
I obviously removed the channel name, domain and application key for security but the rest is accurate. And here's what I see in my browser console:
Response: {"event":"pusher:connection_established","data":"{\"socket_id\":\"166323189.236668505\",\"activity_timeout\":30}"}
Response: {"event":"pusher_internal:subscription_succeeded","channel":"aaaaaa.bbbbbbbb"}
When I send a request from the (working) CMS server, I get a OK response from the socket server and the related device will reboot or whatever I asked it to do. When I send the exact same response from my test script, I see the request get logged in the websockets.log file on the socket server but no response is logged like it is with the requests from the CMS server. And no response prints in the browser console even though I do see the responses print in the browser console for my test script when I send them from the CMS so I know the subscription is working correctly. Also the devices do not reboot.
// client.js
const webSocket = new WebSocket('wss://127.0.0.1:8081');
webSocket.addEventListener('open', (message) => {
alert(message);
})
const text = document.getElementById('text');
const button = document.getElementById('button');
button.onclick = () => {
webSocket.send(text.value);
}
// server.js
import { Server } from 'net';
const server = new Server();
server.on('connection', (socket) => {
console.log(socket);
socket.on('data', (data) => {
})
});
server.listen(8081, '127.0.0.1', () => {
console.log('Server running at port 8081');
});
The problem that I'm facing is:
When I load the page the socket is printed in the console of the server (I can get the remote address and remote port)
No matter what I do, the connection in the client is always pending. I tried Chrome, Brave, Mozilla and Safari and no one seems to work.
What am I missing? I tried to not send the message until the connection is ready, but I never get that state in my PC. The alert in the client never pops, even if I establish the onopen property without an event.
Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
at button.onclick
A webSocket client must connect to a webSocket server. webSocket is a specific connection algorithm (that starts with an http request and then switches to the webSocket protocol) and a specific data format. So, a webSocket client must have a webSocket server to connect to. Your server is a generic TCP server that does not support webSocket connections.
The client will initially establish a TCP socket to your server, then send an http request over that socket, and then it will sit there waiting for an appropriate response to the http request it sent. Since your server never sends that response, it will just sit there waiting until eventually it will timeout and close the socket. This is why you see it stuck in the pending state. It's still waiting for the rest of the webSocket connection sequence to happen and it never does.
If you're curious how the webSocket connection scheme and data format work, you can see a nice description of it here.
Relevant StackOverflow answers:
How does WebSockets server architecture work?
What's the difference between WebSocket and plain socket communication?
Do websocket implementations use http protocol internally?
Overview of webSocket connection scheme
How WebSocket server handles multiple incoming connection requests?
Hi sorry my first stack overflow question so I'll do my best. I've read through dozens of related questions but none seem to provide me with my answer.
I've recently started working with Node.js as I need websockets for some functionality on my website and Node.js seemed to be the popular choice. My website has an SSL Certificate through LetsEncrypt so I've added the cert and key files to my WSS configuration file 'index.js' as shown below:
const fs = require("fs");
const https = require("https");
const WebSocket = require("ws");
const server = https.createServer({
cert: fs.readFileSync("/etc/letsencrypt/live/my_domain.com/cert.pem"),
key: fs.readFileSync("/etc/letsencrypt/live/my_domain.com/privkey.pem"),
requestCert: true,
rejectUnauthorized: false
});
const wss = new WebSocket.Server({ server });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
server.listen(8080, () => console.log("Listening on port :8080"))
When I node index.js on my server through the terminal I get no errors and it outputs: 'Listening on port :8080' as expected. When I then navigate to a simple index.html page I made to test this was working with the following code:
<script>
const socket = new WebSocket("wss://my_domain.com:8080");
socket.addEventListener("open", function (event) {
console.log("We are connected!");
ws.send("Hi! I've connected!");
});
socket.addEventListener("message", function (event) {
console.log(e.data);
});
</script>
I just get the following console error in browsers:
Firefox:
Firefox can’t establish a connection to the server at wss://my_domain.com:8080/.
Chrome:
WebSocket connection to 'wss://my_domain.com:8080/' failed:
(anonymous) # index.html:60
I can't see any other details in the Network inspector tools but if there's anything I can provide for extra clarity/context please ask and I'll respond asap.
EDIT: This article was suggested but does not seem to fix the problem: in their question it works in chrome but not in firefox, mine has yet to work in any browser. Also in the answers on that post they suggest going to a 'normal page on the same server' to accept the certificate but I can't seem to trigger a dialogue box on any of my pages.
I also think my certificate is NOT self-signed as all these posts seem to be but I honestly don't know:
Screenshot of certificate info
After hours of trying to find complicated answers to complicated questions it ended up being a simple firewall issue so thought i'd come back and post what fixed it for me incase anyone else runs into a similar issue in the future.
I simply ran the following command on the server:
ufw allow 3000/tcp
Good luck everyone :)
So I wrote a Node.js WebSocket server and tested it on my computer. I ran the server by typing node server.js in my command line, and in my Node.js I include:
const websocketServer = new WebSocket.Server({
port: 8080
});
To create the WebSocket server. I then wrote a JavaScript (and HTML and CSS) client that connects to that WebSocket server, I ran that client using Adobe Brackets IDE, and established a WebSocket connection to my WebSocket server running on my localhost by saying let websocket = new WebSocket("ws://localhost:8080");
Everything worked perfectly. I worked on both the client and WebSocket server for days and days with no issues at all.
Now, my client and WebSocket server are finished, and I want to deploy my WebSocket server onto Heroku so that other users can connect to it and use it using my client. My client is uploaded onto a separate webserver where users can access it.
So, I deployed my WebSocket server onto Heroku and I deployed my client onto my separate server. In my client I changed the line let websocket = new WebSocket("ws://localhost:8080"); to let websocket = new WebSocket("ws://cryptic-bayou-05102.herokuapp.com"); (cryptic-bayou-05102 is the automatically generated name given to my WebSocket server by Heroku)
However, now when I load my client in my browser, I get an error saying
WebSocket connection to 'ws://cryptic-bayou-05102.herokuapp.com/' failed: Error during WebSocket handshake: Unexpected response code: 307
I believe that the issue is in my WebSocket server, where I have the code:
const websocketServer = new WebSocket.Server({
port: 8080
});
I assume that this code will not work on Heroku since Heroku probably doesn't work the same as a regular server, and so there's no such thing as "port:8080" and requests coming in are directed elsewhere. From what I've found online, I need to somehow configure my WebSocket server to dynamically adjust the port that it listens on according to what Heroku assigns it.
So... My question is, how do I do that? What do I need to change to allow my WebSocket server and client to establish a WebSocket connection?
Thanks in advance! Any answer is a huge help.
Update:
I've continued to look into this for the last couple hours. I can't seem to find anybody else getting a 307 error. I've found many 400/500 errors, but nobody seems to be seeing a 307 error...
I tried one solution that I found online which is to use +process.env.PORT as the port to run the server on, so I tried it out and it didn't change a thing. I logged out the value of +process.env.PORT and using heroku logs, it gave me Listening on port: 18201 which is perfect, and exactly what I want.... However I am still getting the same error.
On top of this, I went back and read through the code of an older Node.js server+client project of mine from a while back (also hosted on Heroku) and the code there is exactly the same as my code here... I'm doing the exact same things which have worked for me before with no error, except now I can't get them to work without giving me an error... It's quite frustrating.
Edit again:
I just wanted to add (for clarification) that I'm getting no server-side errors at all, and my server logs every 5 seconds that it's still running and that everything is still working. It's only the client that has an error. (Also, the server never seems to acknowledge that there was a request to connect, it's like the server never even receives the request sent from the client.)
Another update:
Okay... So I thought that the issue might be that I am attempting to establish a ws connection without creating a http server to upgrade from, so I changed the code in my WebSocket server from:
const WebSocket = require("ws");
const webSocketServerPort = +process.env.PORT || 80;
const websocketServer = new WebSocket.Server({
port: webSocketServerPort
});
to:
const WebSocket = require("ws");
const http = require("http");
const webSocketServerPort = +process.env.PORT || 80;
const httpServer = http.createServer();
httpServer.listen(webSocketServerPort,function(){
console.log("Server is listening on port " + webSocketServerPort);
});
const websocketServer = new WebSocket.Server({
server: httpServer
});
When I tested that code on my localhost, everything worked perfectly again, and it was like nothing changed (that's good!), but then when I deployed it to Heroku and tried again... The error is still there... What am I doing wrong? If this doesn't fix it, what will? I've been trying for so many hours now to get this to work, and nothing that I've tried has made even a tiny difference...
And yet another update:
Previously I've been only passing in the url of my project when initializing a ws connection, like so let websocket = new WebSocket("ws://cryptic-bayou-05102.herokuapp.com"); and I would get a 307 error in my browser. I did that because every time I boot up the server it listens on a different port, and I thought that Heroku would dynamically re-route me... But when that clearly didn't work, I tried specifying the port after the server booted up, and explicitly connecting to the proper port, like this let websocket = new WebSocket("ws://cryptic-bayou-05102.herokuapp.com:29598");...
And that didn't fix it either! But what it did do is that it made the 307 error go away??? It no longer prints out any errors (the dev console is entirely blank), but there's no connection established and the server never even knows that somebody is trying to connect....... This makes no sense to me. Why would it stop the error from appearing, and yet not have any effect on anything else at all? What in the world is going on? (After about one minute of doing nothing it eventually says that the connection timed out...)
When I try printing out the 307 error to the dev console, I see the following:
Okay I figured it out... Apparently Heroku was silently blocking my requests because they were ws requests. I changed to a wss request and it worked perfectly on the first try. I have no idea why it's that way, but I'm glad that it works.
Apparently Heroku gives a 307 error when you attempt to upgrade from https to ws? I'm not sure why it wouldn't tell me something closer to "Can't change from secure connection to insecure ws connection" but I guess that's what they want... ?
However, that seems very weird to me given that I've made another app in Heroku and successfully upgraded from https to ws without any error at all... I still have no idea why it silently failed every time I tried when it had never done that before, but whatever. I'm happy to have it working finally. (Although it's sad that all this trouble was caused by me literally missing off a single "s" in my request, and Heroku couldn't even clue me in...)
Thank you very very very much for the help #Ders. I really appreciate your time and your help meant a lot to me.
Trying to get Adobe's Socket object up and running. I have this code:
var reply = "";
var conn = new Socket;
// access Adobe’s home page
if (conn.open("www.adobe.com:80"))
{
// send a HTTP GET request
conn.write ("GET /index.html HTTP/1.0\n\n");
// and read the server’s reply
reply = conn.read(999999);
conn.close();
alert(reply.toString());
}
else
{
alert(conn.error);
}
And it doesn't work. conn.error is fired, so I know the problem is with conn.open. This is the error message I get:
Tried a bunch of other sites too; nothing worked. But if I switch www.adobe.com:80 to localhost:8080, everything works as expected.
EDIT
I've definitely narrowed it down to being a proxy problem. But I don't know what to do about it, if I have to fix in my script or if I have to talk to IT to see about allowing proxy connections.
Here's where I'm at with my code:
if (conn.open("proxyserver.com:port"))
{
conn.write ("CONNECT www.adobe.com:443 HTTP/1.0\n\n");
reply = conn.read(999999);
alert(reply.toString());
}
This gets me the following:
But I'm not able to do anything beyond that. I can only do port 443 (https, I think); port 80 doesn't work on any site. I think this is more of a proxy problem than a script problem. When I do port 443 and get a connection, though, I don't know how to do anything with that connection. I tried sending a GET request afterwards and it returned blank.
Make sure your firewall isn't blocking access to your proxy server - the particular port may need to be opened, too.
Or, maybe the proxy is not set up to use port 80? If port 443 is used, isn't that SSL; do you need a certificate? It looks like your proxy only accepts SSL connections.
Maybe try with an ipaddress instead of a domain name: 192.150.14.12:80 is the one the adobe pdf provides.