socketio / socket.io

Realtime application framework (Node.JS server)
https://socket.io
MIT License
61.24k stars 10.12k forks source link

Error during WebSocket handshake: Unexpected response code: 400 #1942

Closed shi-yuan closed 7 years ago

shi-yuan commented 9 years ago

Can't find out a solution, I get this error on the browser console: WebSocket connection to 'ws://.../socket.io/?EIO=2&transport=websocket&sid=p3af7ZNfvogtq6tAAAG0' failed: Error during WebSocket handshake: Unexpected response code: 400.

Hava any advice ?

arnauddri commented 9 years ago

I am experiencing the exact same issue at the moment, any help?

vhf commented 9 years ago

I am also having this issue since I installed a SSL cert on my domain.

Here is a better description of the issue: http://stackoverflow.com/questions/28025073/error-during-websocket-handshake-unexpected-response-code-400-with-nginx-proxy

KieranWebber commented 9 years ago

Im also having a similar issue connecting with with one of the Android library's. Web sockets won't connect to https through either HAproxy doing ssl termination or letting node do ssl directly. Long polling works fine however

shi-yuan commented 9 years ago

I resolve it by changing the domain to the true IP address:

var socket = io.connect('http://182.92.79.215:3007');

tylercb commented 9 years ago

Had the same issue, my app is behind nginx. Making these changes to my Nginx config removed the error.

location / { proxy_pass http://localhost:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; }

This is originally from https://chrislea.com/2013/02/23/proxying-websockets-with-nginx/

mikedavies-dev commented 9 years ago

Same issue here on production server. Development machines do not show the error.

The strange thing is that the connection is working. I can send messages via WebSockets from the server and the client gets them. I can also see the WebSocket connection being established on the server.

I just get this error in developer tools saying:

WebSocket connection to 'wss://.../socket.io/?EIO=3&transport=websocket&sid=2b_v_BXtbwzl5z2yAAAI' failed: Error during WebSocket handshake: Unexpected response code: 400

I'm using Apache ProxyPass to send connections to node.

CaptainCannabis commented 9 years ago

Same here - full functional but Error message in dev tools. Somewhere else i read its related to the apache version - using 2.2.14 on this machine.

rickyk586 commented 9 years ago

Make sure you're socket.io connection isn't going through an Amazon Load Balancer. Or if so, do this: http://blog.flux7.com/web-apps-websockets-with-aws-elastic-load-balancing

napcoder commented 9 years ago

Same issue here, only in production environment. Websockets seems to work correctly, the application works without problems. But on console log I can see this error.

I'm using Nginx and only one server for node, so it seems to be not a load balancing problem. I was already using the solution suggested by tylercb (with the exception of "proxy_set_header Host $host;") and it is not solving the issue.

zscorpio commented 9 years ago

also have problem ,but work well....

spinda commented 9 years ago

I had this same issue. Are you using CloudFlare? Currently, only their Enterprise plan supports WebSockets.

napcoder commented 9 years ago

Solved for me. It was due to wrong socket.io address in nginx configuration, that was not matching the path using the websocket.

rudolfschmidt commented 9 years ago

I googled because I got the same problem and I also use nginx. The solution is to add this part

proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host;

into the nginx configuration file like tylercb mentioned.

capr commented 9 years ago

Worked for me. Thanks.

burmisov commented 9 years ago

Got same error directly connecting to my app hosted on Windows Server 2008R2 (no proxy, no IIS). Only dumb intermediate hardware in between.

ghost commented 9 years ago

Work fine after switched host name to ip address, i.e. 127.0.0.1:9000. may caused by httpd ProxyPassReverse

nanyaks commented 9 years ago

In my case, the issue was as a result of cloudfare not supporting websockets on the free plan. I turned off CloudFare for the domain and it worked.

cpres commented 9 years ago

I just needed to add some Apache rewrite conditions to handle the websockets, more info here: http://stackoverflow.com/a/27534443/2044993

alexrosenfeld commented 8 years ago

I know this is an old issue, but since it's high on Google search results, but this might help people:

The reason the connection still works even with this error is that socket.io is falling back to AJAX, which is not optimal and you should fix your server configuration.

Btw, this issue should remain closed, it's not a socket.io issue.

cgodkin commented 8 years ago

@arosenfeld-mentel I keep reading the posts above your comment that "this is not a socket.io issue" but I don't see where anyone says WHAT the issue actually is. I see this myself although, as you say, the connection still seems to work. Any tips would be very gratefully received. Thanks!

alexrosenfeld commented 8 years ago

The issue could be anything really, you need to debug your whole setup. For me it was NGINX, which as reverse proxy needs the additional configuration settings posted above many times. For you could be something else.

Start by debugging the local connection, get it to work without the warning, then move to the production server and make sure you get firewalls, front-facing servers and proxys to cooperate with WebSockets.

It's not a socket.io issue, but it is a WebSockets issue, so make sure the server and the client works well with WebSockets.

cgodkin commented 8 years ago

Thanks for the reply. Everything works locally or through our VPN, but once our firewall is involved, the messages appear. I guess that the firewall is interfering somehow and we'll have to learn how to debug that problem instead of blaming socket.io. Thanks again.

soend commented 8 years ago

Having the exact same issue. I have create stackoverflow (http://stackoverflow.com/questions/34439546/socket-io-with-apache-proxy) question also but things suggested there havent worked for me also yet.

dev-mraj commented 8 years ago

i've put these headers in nginx but still getting the same, but not in browser but in https://toolbox.seositecheckup.com

alkrauss48 commented 8 years ago

Had this issue too, looks like my virtual host (through nginx) wasn't set up properly to accept the Upgrade header. @tylercb's fix from about a year ago fixed it^

eterry1388 commented 8 years ago

@tylercb worked for me.

souzadevinicius commented 8 years ago

+1 This error occurred on openshift environment

rwillett commented 8 years ago

I thought it might be useful if I documented exactly what I did to resolve the issue. This is simply a combination of the various posts above put into a simple post so anybody else finding this issue can get a potential solution easily. I take no credit for the hard work.

We are running

  1. Ubuntu 14.04 LTS Server,
  2. nginx version: nginx/1.4.6 (Ubuntu) as a reverse proxy and SSL gateway.
  3. We do NOT have Apache at all. Its deleted from the system.
  4. We have a node.js server running behind nginx v0.10.25. This listens on port 4001. The external access is via port 4000.
  5. We run ufw on the front and simply allowed port 4000 through.
  6. We manage our own servers and are not using Cloudflare or Openshift
  7. We don't use any load balancer (yet).

We had the same issues as other people of

WebSocket connection to 'ws://XXXXXXXXXX?EIO=2&transport=websocket&sid=p3af7ZNfvogtq6tAAAG0' failed: Error during WebSocket handshake: Unexpected response code: 400.

We updated out nginx file in /etc/nginx/sites-enabled/default to read as follows: (note we've pulled our domain names out)

server {
        listen 4000;
        server_name XXXX.YYYY.ZZZZ;

        root html;
        index index.html index.htm;

        ssl on;
        ssl_certificate /etc/ssl/certs/SSL.crt;
        ssl_certificate_key /etc/ssl/private/server.key;

        ssl_session_timeout 5m;

        # ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; # NOTE WE REMOVE SSLv3
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES1\
28-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECD\
HE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SH\
A256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SH\
A:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

        ssl_prefer_server_ciphers on;
        ssl_dhparam /etc/ssl/private/dhparams.pem;

        location / {
                 proxy_set_header        Host $host;
                 proxy_set_header        X-Real-IP $remote_addr;
                 proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                 proxy_set_header        X-Forwarded-Proto $scheme;

                 # Fix the “It appears that your reverse proxy set up is broken" error.
                 proxy_pass          http://127.0.0.1:4001;
                 proxy_read_timeout  90;

                 proxy_redirect      http://127.0.0.1:4001 https://XXXXX.YYYYY.ZZZZZ;

                 # These three lines added as per https://github.com/socketio/socket.io/issues/1942 to remove the error
                 # WebSocket connection to 'wss://XXXXX.YYYYY.ZZZZZ:4000/socket.io/?EIO=3&transport=websocket&sid=0hsRiXu0q9p6RHQ8AAAC' failed:\
 Error during WebSocket handshake: Unexpected response code: 400 in console.log

                 proxy_http_version 1.1;
                 proxy_set_header   Upgrade $http_upgrade;
                 proxy_set_header   Connection "upgrade";
        }
}

We only needed to add in

  1. proxy_http_version 1.1;
  2. proxy_set_header Upgrade $http_upgrade; 3.proxy_set_header Connection "upgrade";

as we already had

  1. proxy_set_header Host $host;
  2. proxy_pass http://127.0.0.1:4001;

Hope this helps, it worked for us.

Thanks for the help,

Rob

anthony-o commented 8 years ago

I have the same problem when I authenticate with CAS (not with classic form), and I am using Apache with LetEncrypt SSL as a proxy, is there a specific configuration to set?

kikar commented 8 years ago

Trying to deploy the Node.js app on AWS Elastic BeanStalk. I've added a the folder .ebextensions to the root of the server, and inside i've added the file nginx.config that looks like this:

server:
  location /:
    proxy_pass http://localhost:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;

I still get the 400 Error, but at least all the rest of the socket works.

BlaM commented 8 years ago

For Reference: This is the only working config solution I found for socket.io 1.x and Apache 2.4: https://github.com/meteor/meteor/issues/3339#issuecomment-165188938

ProxyPass / http://localhost:3999/
ProxyPassReverse / http://localhost:3999/

RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
RewriteRule .* ws://localhost:3999%{REQUEST_URI} [P]
fireqong commented 8 years ago

using another port, It may work

akoskm commented 8 years ago

@BlaM thanks for the working configuration!

einnjo commented 8 years ago

For anyone experiencing this problem in AWS Elastic Beanstalk, this .ebextension file worked for me:

files:
    "/etc/nginx/conf.d/01_websockets.conf" :
        mode: "000644"
        owner: root
        group: root
        content : |
            upstream nodejs {
                server 127.0.0.1:8081;
                keepalive 256;
            }

            server {
                listen 8080;

                location / {
                    proxy_pass  http://nodejs;
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection "upgrade";
                    proxy_http_version 1.1;
                    proxy_set_header        Host            $host;
                    proxy_set_header        X-Real-IP       $remote_addr;
                    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                }
            }

    "/opt/elasticbeanstalk/hooks/appdeploy/enact/41_remove_eb_nginx_confg.sh":
        mode: "000755"
        owner: root
        group: root
        content : |
            mv /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf /etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf.old

As per the instructions in this thread.

swinston100 commented 8 years ago

@BlaM - I am using an apache server and ELB with Elastic Bean Where should I put the code you provided? Thanks!

BlaM commented 8 years ago

I have no clue about Elastic Bean, but the code snippet I posted goes into Apache host files.

l-zhi commented 8 years ago

@tylercb Thanks! it's worked for me~

erperejildo commented 8 years ago

Anyone not using nginx facing same issue?

deliverymanager commented 8 years ago

Yes I am facing the same issues using Elastic Beanstalk with a single server (node and nginx) without Elastic Load Balancer. I do not know how to change from http/https to ssl/tls

iwalz commented 8 years ago

Same issue with HAProxy here

willworks commented 8 years ago

Worked for me. Thanks. And you should pay attention to the order

proxy_set_header   Upgrade $http_upgrade;
proxy_set_header   Connection "upgrade";
deliverymanager commented 8 years ago

yes this did it for me too.

jsrraman commented 8 years ago

I am also facing this issue. Even with 400 error, the websocket communication between client and server is fine. This is in our development environment.

Can somebody tell me whether this would be an issue in the production environment.

0x5e5e commented 7 years ago

FYI: connecting to a sails backend using socket.io hosted on Heroku using the postgres addon will throw this error in your browser if your io.sails.url is not https. Very specific case but hopefully this helps anyone with the same stack searching for this on google

visibleajay commented 7 years ago

Hey Everybody,

I am also facing the same issue on my localhost machine. We are using python-flask as a server and HTML/CSS/JS as a frontend.

In the Frontend to connect with Websocket Server we have used var socket = io.connect('ws://url/namespace', { 'transports': ['websocket'] });

When I run the application it throws an error WebSocket connection to 'ws://url/namespace/socket.io/?EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 400

Do tell us if you need more information.

Any Help is appreciated. Thanks for Reading it.

Regards Ajay

hli000 commented 7 years ago

I got same error on the webrtc sample app. On the server side, the code is

var server = require('http').Server(app); var io = require('socket.io')(server); var WebRTC = require('../../'); app.use(express.static(__dirname)); var io = require('socket.io')(server);

After comment out the second "require('socket.io')" the 400 error message goes away.

Need to dig further for why...but you can check if your app tries to make same connection twice.

travisbmiller commented 7 years ago

Hey guys I know this discussion has been going a while and wanted to post a resource that solved this problem for me using AWS EBS with Application Load Balancer.

https://mixmax.com/blog/deploying-meteor-to-elastic-beanstalk-1

Hopes this helps.

Travis

unixzilla commented 7 years ago

I have same problem when I use etherpad-lite. I found an approach to fix Apache ProxyPass issue. I am using Apache http 2.2 uses backprot from http 2.4 wstunnel module so i think that can fix v.2.4 too.

First I have modified socket.io-client/socket.io.js look for WS.prototype.uri = function() return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query; then change to:

return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path +'ws/'+ query; save it and restart node.

Second, modify vhost.conf or ssl.conf add following to VirtualHost:

        ProxyPass "/etherpad/socket.io/ws/" "ws://localhost:9001/socket.io/"
        ProxyPassReverse "/etherpad/socket.io/ws/" "ws://localhost:9001/socket.io/"

        ProxyPass "/etherpad/socket.io/" "http://localhost:9001/socket.io/"
        ProxyPassReverse "/etherpad/socket.io/" "http://localhost:9001/socket.io/"

        ProxyPass /etherpad/ http://localhost:9001/
        ProxyPassReverse /etherpad/ http://localhost:9001/
        CacheDisable *

        ProxyPreserveHost on
        <Proxy *>
                Options FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Proxy>

`

Restart apache httpd, enjoy~

hoanganh25991 commented 7 years ago

For Apache, follow @cpres answer, it works. My conf

<VirtualHost *:80>
    ServerAdmin lehoanganh25991@gmail.com
    ServerName reservation.tinker.press

    DocumentRoot /var/www/html/node-js-order-socket-demo
    <Directory />
        Options -Indexes +FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

    RewriteEngine on
    RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
    RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
    RewriteRule .* ws://127.0.0.1:3001%{REQUEST_URI} [P]

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyVia Full
    <Proxy *>
        Require all granted
    </Proxy>

    ProxyPass / "http://127.0.0.1:3001/"
    ProxyPassReverse / "http://127.0.0.1:3001/"

    ErrorLog ${APACHE_LOG_DIR}/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

apache-websocket-use-mode-rewrite

djlitvak commented 7 years ago

I also had to adjust my elastic load balancer to use TCP over port 80 instead of HTTP over port 80.