OOPS Studio
OOPS Studio

Reputation: 836

How do I connect to a `WebSocket` server running on Heroku?

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: image of 307 error in dev console

Upvotes: 1

Views: 2090

Answers (1)

OOPS Studio
OOPS Studio

Reputation: 836

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.

Upvotes: 3

Related Questions