New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
shi-yuan opened this Issue Jan 14, 2015 · 92 comments

Comments

Projects
None yet
@shi-yuan

shi-yuan commented Jan 14, 2015

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

This comment has been minimized.

Show comment
Hide comment
@arnauddri

arnauddri Jan 14, 2015

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

arnauddri commented Jan 14, 2015

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

@vhf

This comment has been minimized.

Show comment
Hide comment
@vhf

vhf Jan 19, 2015

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

vhf commented Jan 19, 2015

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

This comment has been minimized.

Show comment
Hide comment
@KieranWebber

KieranWebber Jan 19, 2015

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

KieranWebber commented Jan 19, 2015

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 shi-yuan closed this Jan 26, 2015

@shi-yuan

This comment has been minimized.

Show comment
Hide comment
@shi-yuan

shi-yuan Jan 26, 2015

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

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

shi-yuan commented Jan 26, 2015

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

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

@tylercb

This comment has been minimized.

Show comment
Hide comment
@tylercb

tylercb Mar 17, 2015

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/

tylercb commented Mar 17, 2015

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/

@ant-fx

This comment has been minimized.

Show comment
Hide comment
@ant-fx

ant-fx Apr 9, 2015

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.

ant-fx commented Apr 9, 2015

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

This comment has been minimized.

Show comment
Hide comment
@CaptainCannabis

CaptainCannabis Apr 14, 2015

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.

CaptainCannabis commented Apr 14, 2015

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

This comment has been minimized.

Show comment
Hide comment
@rickyk586

rickyk586 Apr 19, 2015

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

rickyk586 commented Apr 19, 2015

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

This comment has been minimized.

Show comment
Hide comment
@napcoder

napcoder Apr 24, 2015

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.

napcoder commented Apr 24, 2015

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

This comment has been minimized.

Show comment
Hide comment
@zscorpio

zscorpio Apr 28, 2015

also have problem ,but work well....

zscorpio commented Apr 28, 2015

also have problem ,but work well....

@spinda

This comment has been minimized.

Show comment
Hide comment
@spinda

spinda Apr 28, 2015

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

spinda commented Apr 28, 2015

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

@napcoder

This comment has been minimized.

Show comment
Hide comment
@napcoder

napcoder Apr 28, 2015

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

napcoder commented Apr 28, 2015

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

@rudolfschmidt

This comment has been minimized.

Show comment
Hide comment
@rudolfschmidt

rudolfschmidt May 6, 2015

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.

rudolfschmidt commented May 6, 2015

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

This comment has been minimized.

Show comment
Hide comment
@capr

capr May 17, 2015

Worked for me. Thanks.

capr commented May 17, 2015

Worked for me. Thanks.

@burmisov

This comment has been minimized.

Show comment
Hide comment
@burmisov

burmisov May 25, 2015

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

burmisov commented May 25, 2015

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

@sunnymix

This comment has been minimized.

Show comment
Hide comment
@sunnymix

sunnymix Jun 15, 2015

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

sunnymix commented Jun 15, 2015

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

@nanyaks

This comment has been minimized.

Show comment
Hide comment
@nanyaks

nanyaks Aug 9, 2015

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.

nanyaks commented Aug 9, 2015

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

This comment has been minimized.

Show comment
Hide comment
@cpres

cpres Sep 30, 2015

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

cpres commented Sep 30, 2015

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

@alexrosenfeld

This comment has been minimized.

Show comment
Hide comment
@alexrosenfeld

alexrosenfeld Dec 16, 2015

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.

alexrosenfeld commented Dec 16, 2015

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

This comment has been minimized.

Show comment
Hide comment
@cgodkin

cgodkin Dec 17, 2015

@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!

cgodkin commented Dec 17, 2015

@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

This comment has been minimized.

Show comment
Hide comment
@alexrosenfeld

alexrosenfeld Dec 17, 2015

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.

alexrosenfeld commented Dec 17, 2015

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.

@spookyUnknownUser

This comment has been minimized.

Show comment
Hide comment
@spookyUnknownUser

spookyUnknownUser Dec 21, 2017

@rafapetter Check that you haven't required socket.io twice, I was moving setting up socket.io in www/bin to app.js and accidentally left a require socket.io in the bin which was causing this error.

spookyUnknownUser commented Dec 21, 2017

@rafapetter Check that you haven't required socket.io twice, I was moving setting up socket.io in www/bin to app.js and accidentally left a require socket.io in the bin which was causing this error.

@prapansak

This comment has been minimized.

Show comment
Hide comment
@prapansak

prapansak Dec 27, 2017

Just adding {transports: ['websocket']} option to the Socket.io client.

look like this.

import io from 'socket.io-client'
const socket = io('http://localhost:5000', {transports: ['websocket']})

prapansak commented Dec 27, 2017

Just adding {transports: ['websocket']} option to the Socket.io client.

look like this.

import io from 'socket.io-client'
const socket = io('http://localhost:5000', {transports: ['websocket']})
@rafapetter

This comment has been minimized.

Show comment
Hide comment
@rafapetter

rafapetter Dec 27, 2017

@spookyUnknownUser on the server the socket.io is required only once.

@prapansak the client is a simple javascript file, inside a window.onload function, no ES6 import allowed. But I do follow the How to Use section:
<script src="/socket.io/socket.io.js"></script>

And when calling the socket as you've suggested:
const socket = io('http://localhost:5000', {transports: ['websocket']})

I get this error: WebSocket connection to 'ws://localhost:1337/socket.io/?EIO=3&transport=websocket' failed: Invalid frame header

Thanks guys, if you have any other idea let me know and I'll try it here.

rafapetter commented Dec 27, 2017

@spookyUnknownUser on the server the socket.io is required only once.

@prapansak the client is a simple javascript file, inside a window.onload function, no ES6 import allowed. But I do follow the How to Use section:
<script src="/socket.io/socket.io.js"></script>

And when calling the socket as you've suggested:
const socket = io('http://localhost:5000', {transports: ['websocket']})

I get this error: WebSocket connection to 'ws://localhost:1337/socket.io/?EIO=3&transport=websocket' failed: Invalid frame header

Thanks guys, if you have any other idea let me know and I'll try it here.

@rafapetter

This comment has been minimized.

Show comment
Hide comment
@rafapetter

rafapetter Dec 27, 2017

Ok, finally got it solved!

@spookyUnknownUser your idea encourage me to look further for duplications. And as it turns out, on the server right after server.listen I was doing this:

io.attach(server, {
  pingInterval: 40000,
  pingTimeout: 25000,
});

Which in a way I guess is attaching the server a second time. So I removed it and right at the beginning, when requiring socket.io I've changed to:

var io = require('socket.io')(server, {
	'pingInterval': 40000,
	'pingTimeout': 25000
});

Now, no issues are shown, and everything works fine.

Thanks again for the insights guys

rafapetter commented Dec 27, 2017

Ok, finally got it solved!

@spookyUnknownUser your idea encourage me to look further for duplications. And as it turns out, on the server right after server.listen I was doing this:

io.attach(server, {
  pingInterval: 40000,
  pingTimeout: 25000,
});

Which in a way I guess is attaching the server a second time. So I removed it and right at the beginning, when requiring socket.io I've changed to:

var io = require('socket.io')(server, {
	'pingInterval': 40000,
	'pingTimeout': 25000
});

Now, no issues are shown, and everything works fine.

Thanks again for the insights guys

@imaimai86

This comment has been minimized.

Show comment
Hide comment
@imaimai86

imaimai86 Jan 9, 2018

I have my socket server on EBS(AWS Elastic beanstalk). I faced similiar issue in the production environment, but could fix the issue without migrating to application load balancer and without changing ngnix or apache configurations.

Changes I made to solve this issue: Instead of https, i allowed ssl on 443 to my application port and opened port 443 on my security group

ebs_lb
ebs_sg

imaimai86 commented Jan 9, 2018

I have my socket server on EBS(AWS Elastic beanstalk). I faced similiar issue in the production environment, but could fix the issue without migrating to application load balancer and without changing ngnix or apache configurations.

Changes I made to solve this issue: Instead of https, i allowed ssl on 443 to my application port and opened port 443 on my security group

ebs_lb
ebs_sg

@mspoulsen

This comment has been minimized.

Show comment
Hide comment
@mspoulsen

mspoulsen Jan 31, 2018

For those on AWS: Use the Application Load Balancer and make sure you have stickiness enabled on the Target Group.

mspoulsen commented Jan 31, 2018

For those on AWS: Use the Application Load Balancer and make sure you have stickiness enabled on the Target Group.

@NickDuncanZA

This comment has been minimized.

Show comment
Hide comment
@NickDuncanZA

NickDuncanZA Feb 6, 2018

Turns out this was happening intermittently on our server when it was overloaded and within peak usage time.

Allowing the default settings while io.connect fires off creates XHR requests and a WS request shortly after (as mentioned above). All these XHR requests were overloading the server and thus returning the 400 errors. By using the suggestions above of adding transports: ['websocket']} to the client code the issue has been resolved. Will post an update if the 400 errors persist but it seems solid for now.

NickDuncanZA commented Feb 6, 2018

Turns out this was happening intermittently on our server when it was overloaded and within peak usage time.

Allowing the default settings while io.connect fires off creates XHR requests and a WS request shortly after (as mentioned above). All these XHR requests were overloading the server and thus returning the 400 errors. By using the suggestions above of adding transports: ['websocket']} to the client code the issue has been resolved. Will post an update if the 400 errors persist but it seems solid for now.

@okonsemi

This comment has been minimized.

Show comment
Hide comment
@okonsemi

okonsemi May 11, 2018

have the same issue, neither suggested above server side changes resolved it. On the client side I have socket = io.connect(); in react module and it's able to figure out what server I'm connecting to.
Providing server parameter to connect is kind of a hassle but without it how can I specify { reconnect: true, transports: ['websocket', 'polling'] }? Sounds like an optional parameter is #1 but the crucial one is #2

okonsemi commented May 11, 2018

have the same issue, neither suggested above server side changes resolved it. On the client side I have socket = io.connect(); in react module and it's able to figure out what server I'm connecting to.
Providing server parameter to connect is kind of a hassle but without it how can I specify { reconnect: true, transports: ['websocket', 'polling'] }? Sounds like an optional parameter is #1 but the crucial one is #2

@yimingsue

This comment has been minimized.

Show comment
Hide comment
@yimingsue

yimingsue May 14, 2018

i added this below, and it worked for me.
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;
}
https://chrislea.com/2013/02/23/proxying-websockets-with-nginx/

yimingsue commented May 14, 2018

i added this below, and it worked for me.
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;
}
https://chrislea.com/2013/02/23/proxying-websockets-with-nginx/

@moak

This comment has been minimized.

Show comment
Hide comment
@moak

moak May 20, 2018

I unfortunately have the same problem, even with the good headers set .. I created a stackoverflow with my config..

https://stackoverflow.com/questions/50431587/proxy-socket-io-fails-to-connect-with-nginx-node-on-docker

moak commented May 20, 2018

I unfortunately have the same problem, even with the good headers set .. I created a stackoverflow with my config..

https://stackoverflow.com/questions/50431587/proxy-socket-io-fails-to-connect-with-nginx-node-on-docker

@bmino

This comment has been minimized.

Show comment
Hide comment
@bmino

bmino May 29, 2018

Make note of the double quotes here:

proxy_set_header Connection "upgrade";

I received this message using single quotes but using doubles quotes resolved it.

bmino commented May 29, 2018

Make note of the double quotes here:

proxy_set_header Connection "upgrade";

I received this message using single quotes but using doubles quotes resolved it.

@ntrabue

This comment has been minimized.

Show comment
Hide comment
@ntrabue

ntrabue Jul 12, 2018

After about an hour of troubleshooting, it seems like there might be some additional configuration needed if you're running your endpoint as a cluster.

ntrabue commented Jul 12, 2018

After about an hour of troubleshooting, it seems like there might be some additional configuration needed if you're running your endpoint as a cluster.

@axhiao

This comment has been minimized.

Show comment
Hide comment
@axhiao

axhiao commented Jul 17, 2018

see here

@kalihos

This comment has been minimized.

Show comment
Hide comment
@kalihos

kalihos Jul 29, 2018

tylercb solution worked for me (NgInx). Thanks!

kalihos commented Jul 29, 2018

tylercb solution worked for me (NgInx). Thanks!

@krumware

This comment has been minimized.

Show comment
Hide comment
@krumware

krumware Jul 30, 2018

The key for us was the proxy_http_version 1.1; in @tylercb's solution

krumware commented Jul 30, 2018

The key for us was the proxy_http_version 1.1; in @tylercb's solution

@mansimas

This comment has been minimized.

Show comment
Hide comment
@mansimas

mansimas Jul 31, 2018

I have edited NginX config on my server according those many comments.
But it works partially. At first, after server restart, it works bad. Mostly with hard-refresh. Later it works better, just sometimes need hard refresh.
Locally with sails lift it works
But if i am using locally sails lift --prod then i get the same thing, that socket cannot connect and 400 bad response. But after some tries it is again stable.

This seems still not solved - no final solution found why we have this..

mansimas commented Jul 31, 2018

I have edited NginX config on my server according those many comments.
But it works partially. At first, after server restart, it works bad. Mostly with hard-refresh. Later it works better, just sometimes need hard refresh.
Locally with sails lift it works
But if i am using locally sails lift --prod then i get the same thing, that socket cannot connect and 400 bad response. But after some tries it is again stable.

This seems still not solved - no final solution found why we have this..

darrachequesne added a commit to socketio/socket.io-website that referenced this issue Jul 31, 2018

@darrachequesne

This comment has been minimized.

Show comment
Hide comment
@darrachequesne

darrachequesne Jul 31, 2018

Contributor

I added the various configurations in the documentation: https://socket.io/docs/using-multiple-nodes/

Any suggestion for improvement is welcome! => https://github.com/socketio/socket.io-website

Contributor

darrachequesne commented Jul 31, 2018

I added the various configurations in the documentation: https://socket.io/docs/using-multiple-nodes/

Any suggestion for improvement is welcome! => https://github.com/socketio/socket.io-website

nanozuki pushed a commit to nanozuki/tt392 that referenced this issue Aug 7, 2018

@slaveofcode

This comment has been minimized.

Show comment
Hide comment
@slaveofcode

slaveofcode Aug 7, 2018

I just face this problem and still got an error even disable my nginx. Finally the problem because of express-status-monitor middleware on express, this makes HTTP call on the first (request) handshake of WebSocket goes failed.

I try to disable that middleware and the WebSocket working well

slaveofcode commented Aug 7, 2018

I just face this problem and still got an error even disable my nginx. Finally the problem because of express-status-monitor middleware on express, this makes HTTP call on the first (request) handshake of WebSocket goes failed.

I try to disable that middleware and the WebSocket working well

@arunsatyarth

This comment has been minimized.

Show comment
Hide comment
@arunsatyarth

arunsatyarth Sep 2, 2018

There are several reasons why you would get 400 during the handshake. Following are few things that could be tried

  1. Enable 443 in (ufw/Other) firewalls as well as settings of (AWS/Google cloud/Other) console
  2. Do not enable TLS in nodejs server. Do it through nginx.
  3. Use following nginx config
    Note: This only works if your socket.io connection is already working but using long polling instead of websockets. Add below code and it will start using websocket.
        location /{
            proxy_pass http://127.0.0.1:5000/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
        }

arunsatyarth commented Sep 2, 2018

There are several reasons why you would get 400 during the handshake. Following are few things that could be tried

  1. Enable 443 in (ufw/Other) firewalls as well as settings of (AWS/Google cloud/Other) console
  2. Do not enable TLS in nodejs server. Do it through nginx.
  3. Use following nginx config
    Note: This only works if your socket.io connection is already working but using long polling instead of websockets. Add below code and it will start using websocket.
        location /{
            proxy_pass http://127.0.0.1:5000/;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
        }
@PinkyRabbit

This comment has been minimized.

Show comment
Hide comment
@PinkyRabbit

PinkyRabbit Sep 7, 2018

Maybe it will be help to some one. I got this error when created two instances of socket.io in my app. I called io = socketio(server) twise and got error 400. That is some sort of stupid errors but... that was mine.

PinkyRabbit commented Sep 7, 2018

Maybe it will be help to some one. I got this error when created two instances of socket.io in my app. I called io = socketio(server) twise and got error 400. That is some sort of stupid errors but... that was mine.

@Hmachalani

This comment has been minimized.

Show comment
Hide comment
@Hmachalani

Hmachalani Sep 12, 2018

Make sure you enable Sticky sessions in your application load balancer (don't use classic load balancer). If you don't use sticky sessions, you'll probably get the 400 errors randomly.

This is because when the upgrade from polling to websocket is attempted, it’s possible that the load balancer balances the upgrade request to a server that never encountered this socket id and throws the 400 error. More details here: https://socket.io/docs/using-multiple-nodes/

Hmachalani commented Sep 12, 2018

Make sure you enable Sticky sessions in your application load balancer (don't use classic load balancer). If you don't use sticky sessions, you'll probably get the 400 errors randomly.

This is because when the upgrade from polling to websocket is attempted, it’s possible that the load balancer balances the upgrade request to a server that never encountered this socket id and throws the 400 error. More details here: https://socket.io/docs/using-multiple-nodes/

@Hmachalani

This comment has been minimized.

Show comment
Hide comment
@Hmachalani

Hmachalani Sep 12, 2018

Also, if you're using elastic beanstalk, add the following websocket.config file in the .ebextensions folder to support Nginx upgrading to Websockets:

container_commands:
  enable_websockets:
    command: |
     sed -i '/\s*proxy_set_header\s*Connection/c \
              proxy_set_header Upgrade $http_upgrade;\
              proxy_set_header Connection "upgrade";\
      ' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

Hmachalani commented Sep 12, 2018

Also, if you're using elastic beanstalk, add the following websocket.config file in the .ebextensions folder to support Nginx upgrading to Websockets:

container_commands:
  enable_websockets:
    command: |
     sed -i '/\s*proxy_set_header\s*Connection/c \
              proxy_set_header Upgrade $http_upgrade;\
              proxy_set_header Connection "upgrade";\
      ' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

@LeonAppDev

This comment has been minimized.

Show comment
Hide comment
@LeonAppDev

LeonAppDev Oct 4, 2018

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.

So at least this works when you use nginx as reverse proxy, here is the explanation

WebSocket proxying
To turn a connection between a client and server from HTTP/1.1 into WebSocket, the protocol switch mechanism available in HTTP/1.1 is used.

There is one subtlety however: since the “Upgrade” is a hop-by-hop header, it is not passed from a client to proxied server. With forward proxying, clients may use the CONNECT method to circumvent this issue. This does not work with reverse proxying however, since clients are not aware of any proxy servers, and special processing on a proxy server is required.

Since version 1.3.13, nginx implements special mode of operation that allows setting up a tunnel between a client and proxied server if the proxied server returned a response with the code 101 (Switching Protocols), and the client asked for a protocol switch via the “Upgrade” header in a request.

As noted above, hop-by-hop headers including “Upgrade” and “Connection” are not passed from a client to proxied server, therefore in order for the proxied server to know about the client’s intention to switch a protocol to WebSocket, these headers have to be passed explicitly:

location /chat/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
A more sophisticated example in which a value of the “Connection” header field in a request to the proxied server depends on the presence of the “Upgrade” field in the client request header:

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        ...

        location /chat/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
By default, the connection will be closed if the proxied server does not transmit any data within 60 seconds. This timeout can be increased with the proxy_read_timeout directive. Alternatively, the proxied server can be configured to periodically send WebSocket ping frames to reset the timeout and check if the connection is still alive.

LeonAppDev commented Oct 4, 2018

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.

So at least this works when you use nginx as reverse proxy, here is the explanation

WebSocket proxying
To turn a connection between a client and server from HTTP/1.1 into WebSocket, the protocol switch mechanism available in HTTP/1.1 is used.

There is one subtlety however: since the “Upgrade” is a hop-by-hop header, it is not passed from a client to proxied server. With forward proxying, clients may use the CONNECT method to circumvent this issue. This does not work with reverse proxying however, since clients are not aware of any proxy servers, and special processing on a proxy server is required.

Since version 1.3.13, nginx implements special mode of operation that allows setting up a tunnel between a client and proxied server if the proxied server returned a response with the code 101 (Switching Protocols), and the client asked for a protocol switch via the “Upgrade” header in a request.

As noted above, hop-by-hop headers including “Upgrade” and “Connection” are not passed from a client to proxied server, therefore in order for the proxied server to know about the client’s intention to switch a protocol to WebSocket, these headers have to be passed explicitly:

location /chat/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
A more sophisticated example in which a value of the “Connection” header field in a request to the proxied server depends on the presence of the “Upgrade” field in the client request header:

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        ...

        location /chat/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
By default, the connection will be closed if the proxied server does not transmit any data within 60 seconds. This timeout can be increased with the proxy_read_timeout directive. Alternatively, the proxied server can be configured to periodically send WebSocket ping frames to reset the timeout and check if the connection is still alive.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment