32

I have a server with ubuntu 16.04, kestrel and nginx as a proxy server that redirects to localhost where my app is. And my app is on Asp.Net Core 2. I'm trying to add push notifications and using SignalR core. On localhost everything is working well, and on a free hosting with iis and windows as well. But when I deploy my app on the linux server I have an error:

signalr-clientES5-1.0.0-alpha2-final.min.js?v=kyX7znyB8Ce8zvId4sE1UkSsjqo9gtcsZb9yeE7Ha10:1 WebSocket connection to 'ws://devportal.vrweartek.com/chat?id=210fc7b3-e880-4d0e-b2d1-a37a9a982c33' failed: Error during WebSocket handshake: Unexpected response code: 204

But this error occurs only if I request my site from different machine via my site name. And when I request the site from the server via localhost:port everything is fine. So I think there is a problem in nginx. I read that I need to configure it for working with websockets which are used in signalr for establishing connection but I wasn't succeed. May be there is just some dumb mistake?

enter image description here

Artyom
  • 654
  • 2
  • 7
  • 16

3 Answers3

49

I was able to solve this by using $http_connection instead of keep-alive or upgrade

server {
  server_name example.com;

  location / {
    proxy_pass http://localhost:5000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}

I did this because SignalR was also trying to use POST and GET requests to my hubs, so doing just an Upgrade to the connection in a separate server configuration wasn't enough.

voidraen
  • 748
  • 10
  • 18
  • Not sure about the security implications for this. If someone has any thoughts on that, please let me know. – voidraen May 31 '18 at 23:22
  • 2
    This also solved it in my situation. Also other requests not for the hub remains without the connection upgrade – Geert Oct 03 '18 at 08:08
  • 6
    FWIW, Microsoft does now have documentation for [Configure Nginx](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1#configure-nginx) & [Linux with Nginx](https://learn.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/server?view=aspnetcore-3.1#linux-with-nginx) describing these. – Mark G Sep 08 '20 at 18:35
  • Thanks. works for me! – Ali Rasouli Jun 24 '23 at 09:35
34

The problem is the nginx configuration file. If you are using the default settings of the ASP.NET Core deployment guide then the problem is the one of the proxy headers. WebSocket requires Connection header as "upgrade".

You have to set a new path for SignalR Hub on nginx configuration file.

such as

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

You can read my full blog post

https://medium.com/@alm.ozdmr/deployment-of-signalr-with-nginx-daf392cf2b93

alim
  • 677
  • 5
  • 19
1

For SignalR in my case, besides the "proxy_set_header" settings, there is another critical setting "proxy_buffering off;".

So, a full example is now like,

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

  server {
    server_name some_name;
    listen 80 default_server;

    root /path/to/wwwroot;
    
    # Configure the SignalR Endpoint
    location /hubroute {
      proxy_pass http://localhost:5000;

      # Configure WebSockets
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_cache_bypass $http_upgrade;

      # Configure ServerSentEvents
      proxy_buffering off;

      # Configure LongPolling
      proxy_read_timeout 100s;

      proxy_set_header Host $host;
    }
  }
}

See reference: Document reverse proxy usage with SignalR

Kyle LI
  • 21
  • 6