Websocket returns status 200 instead of 101 (flask socket.io) - javascript

I've done quite a bit of reading around to try and solve this issue but I'm still stuck. My problem is with trying to get the websocket handshake to complete using socket.io client side and flask_socket.io server side.
I can run the flask development server on my local machine using:
app = Flask(__name__)
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
socketio = SocketIO(app)
socketio.run(app)
...
and if I point chrome to localhost:5000 and press the button which I have linked to opening a websocket it works fine and chrome network tab shows status 101.
However on uploading the code to a remote machine and again using flask's development server but changing the port to 80,
socketio.run(app,host='0.0.0.0',port=80)
the websocket handshake stops working and gives status 200 instead.
WebSocket connection to 'ws://example.com/socket.io/?EIO=3&transport=websocket&sid=cfb1949b243b42578fe422782a0db359' failed: Error during WebSocket handshake: Unexpected response code: 200
All websocket messages are now sent over xhr polling instead of inside the websocket frame.
I've followed all of the guides I can find on google relating to this but with no success. I was previously using nginx and gunicorn and followed the advice to change the nginx conf to allow upgrade to websockets but that didn't solve the problem. So I simplified to using the flask development server but I still haven't been able to get a successful handshake.

I found a solution after finding a similar problem posted here https://nolanlawson.com/2013/05/31/web-sockets-with-socket-io-node-js-and-nginx-port-80-considered-harmful/#comment-85425.
It turns out many public wifi networks block websockets when they are running on port 80. However often ports 443 and 8080 are not blocked. You can find out which ports are blocked from this website: http://websocketstest.com/. I just moved the address of my websocket from example.com to example.com:8080.

I ran into a similar problem but due to a different reason. When using flask-socketio you have to install gevent-websocket or else it's going to use long-polling and you'll see a lot of 200 responses. Thus, my solution to that problem was just.
pip install gevent-websocket

Related

Websockets to Heroku are giving a 404 on chrome/firefox

I have my Django application deployed on heroku. It uses websockets, and everything is configured properly. When I go to my site, the websockets fail with WebSocket connection to 'wss://<url>' failed: Error during WebSocket handshake: Unexpected response code: 404. I did some digging and it's apparently due to chrome blocking the websockets? I came across this issue which sounds like what I'm getting, but the answer did not fix it for me.
Can someone explain what's going on here, and potentially how to fix it?
So the solution was nothing to do with heroku. I was using gunicorn to deploy my application, and that does not support websockets, so when the website hit my websocket endpoint gunicorn threw back a 404. I switched to daphne, and added web: daphne <application>.asgi:application --port $PORT --bind 0.0.0.0 to the Procfile, and everything started working. This blog post from Heroku helped me out, most specifically This segment.
try using https://<url> inspite of using wss i came across the same issue when i deployed my node.js application on heroku.
hope this will solve your problem too.

Web socket connection does not work over SSL

I have Web Socket that works perfectly fine on localhost and production (https://www.example.com) environment.
However, when I deploy the same code to pp environment (https://pp.example.com) I get WebSocket handshake: Unexpected response code: 404
I have AWS certificate manager generated certificate for domain example.com, with additional domain name www.example.com and pp.example.com
www.example.com and pp.example.com are sitting on different server so they have different ip addresses.
When I go to www.example.com and make the following call,
let ws = new WebSocket("wss://www.example.com/ws");
It works perfectly fine.web socket is connected.
However, when I switch to pp.example.com and make the following call
let ws = new WebSocket("wss://pp.example.com/ws");
I get error from Safari, Firefox and Chrome:
WebSocket connection to 'wss://pp.example.com/ws' failed: Error during
WebSocket handshake: Unexpected response code: 404
Any ideas?
The code are exactly the same.
They are deployed on aws beanstalk.
production environment is using global accelerator + application load balancer + EC2
pp environment is using classic load balancer + EC2
The problems lies in load balancer's listener.
I was using HTTPS for traffic forwarding, while web socket works on TCP level, therefore, it should be SSL TCP instead.
See the attached screenshot at the following for load balancer

ReactJS could not proxy request from localhost:3000 to localhost:3003

I am writing a SPA using create-react-app and am using an expressjs server as my backend. For development I run my frontend test server on port 3000 and my backend expressjs test server on 3003.
I make many API calls client side using Axios so for development convenience I have defined proxy: "http://localhost:3003" in my package.json
This works fine on my laptop, but when running on my workstation I constantly get the error when accessing my app:
Proxy error: Could not proxy request /sockjs-node/487/wrst1bub/websocket from localhost:3000 to http://localhost:3003/. See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNRESET).
I have no idea where this is coming from and I do not use sockjs in any capacity as far as I know. This is a console error and it does not crash my app but it is very annoying and I would like to get rid of it. Any help is greatly appreciated.
In my case, I was using Firefox and for some reasons, it gives me the same error. I tried to use Chrome and it worked!

How to do a reverse proxy with node.js for a shiny app

EDIT
I think the problem might be that the WebSocket connection does not go through the proxy node.js. How to authorize the connection of the WebSocket?
I have a web app hosted on a nodeJS server. On the same vm I also have a shiny serveur hosting an app. I use node to redirect traffic to port 3838 (shiny) when a somes URL are requested.
I use this code on node :
app.use('/the-shiny-app', proxy({target: 'http://localhost:3838', changeOrigin: true}));
With this setting everything works fine on the shiny app when I go on mydomain/the-shiny-app/* except when I try to run code in a code box.
When I try to run code I get this error on the chrome console :
Connection closed. Info: {"type":"close","code":4503,"reason":"The application unexpectedly exited","wasClean":true}
An example of what I mean by code box :
if I do not use node.js and I redirect the traffic (on OS level) from port 80 directly to 3838 everything works fine.
sudo iptables -A PREROUTING -t nat -p tcp --dport 80 -j REDIRECT --to-ports 3838
I do not know exactly what kind of exchange is made between the browser and the shiny server when we run code, but maybe the protocol used is blocked by node.js.
I found the problem. As Antony Gibbs said you need to setup a WebSocket upgrade. I'm using http-proxy-middleware you cans find the doc here : https://github.com/chimurai/http-proxy-middleware

nodejs/curl http request is slow compared to postman rest client

I call a Rest API from node.js and Postman-Rest Client (chrome app).
Always using the same computer, same endpoint and same parameters.
In node.js I get ~400ms for http and ~700ms for https.
In Postman I get ~250ms for http and https.
Libraries I used in node.js: http, https, request, kinvey (node client of the api). All of them got the the same result more or less.
Why my node is slower?
node.js 0.10.36
Edit:
it's not about node, i get the same result with curl.
when running in browser using XMLHttpRequest i get better times.
from analysing the logs I found that TCP connect and SSL handshake takes about 500ms. It may be that TCP connect and SSL handshake works differently in browser.
Here you can find some help.
I am also facing issues with nodejs application server on linux instance. But dont blame nodejs as real issue is in linux systems.
Issue : any outbound request from machine need to find the domain , hence it always lookup the DNS entries & always handshakes with secure/unsecure protocols. This is actually the time taking scenario.
You can verify by doing CURL request.
curl --trace-time -v https://outboundserver.com
Solution : We have to White List IP of outbound server in our own DNS entries. take a look below ...
IN Windows : automatically does the mapping of servers in own dns entries.
IN Linux : We have to manually add the hosts corresponding to IP Address.
Manually add an entry in /etc/hosts file below any configuration like localhost.
127.0.0.1 localhost
outbound.servers.ip.address www.outboundserver.com
Finally check with the curl request again, it should give faster response.
curl --trace-time -v https://outboundserver.com

Categories