Nginx Reverse proxy with gunicorn and python-socketio

Viewed 643

As stated in the title, I am using a python-socketio async server with aiohttp for websocket connections. To deploy my server I use gunicorn. Binding gunicorn to address 0.0.0.0:port works fine, I can connect and had no problems. But now I want to use an nginx reverse proxy to my app and I bind gunicorn to test.sock.

The requests come to the server but a connection is never established. This means my socketio method connect() runs properly but the connection is not established.

Nginx gives me the error

*1 upstream prematurely closed connection while reading response header from upstream,

nginx.conf

worker_processes 1;

error_log  /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
  worker_connections 1024;
  accept_mutex off;
}

http {
  include mime.types;

  default_type application/octet-stream;
  access_log /var/log/nginx/access.log combined;
  sendfile on;

  upstream testapp {
    server unix:/tmp/test.sock fail_timeout=0;
  }

  server {
    listen 80 default_server;
    return 444;
  }

  server {
    listen 80;
    client_max_body_size 4G;

    server_name <myservername>;

    keepalive_timeout 5;

    root /tmp;

    location / {
      try_files $uri @testapp;
    }

    location @testapp {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_buffering off;

      proxy_pass http://testapp;
    }
  }
}

Thanks for your help. Really not sure how I can resolve this issue. Been stuck for quite some time already.

1 Answers

I did figure out what the problem was. Maybe this helps someone. With nginx.conf as

error_log /var/log/error.log info;

events {}

http {

  access_log /var/log/access.log;

  upstream testapp {
    server unix:/tmp/testapp.sock fail_timeout=0;
  }

  server {
    listen 80;
    server_name <myservername>;

    location / {
      proxy_pass http://testapp;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_redirect off;
      proxy_buffering off;
    }

  }
}

everything works like a charm. Turns out Upgrade and Connection Headers are needed to upgrade the connection from http to websocket as we want (which makes perfect sense).

And interestingly proxy_pass needs to be the first line in your location block (I did not find this stated explicitly somewhere, but all examples were like this). I don't know why this is needed, but without it being exactly there it did not work for me.

Related