EventSource / Server-Sent Events via Nginx

Server side using Sinatra with stream block.

 get '/stream', :provides => 'text/event-stream' do stream :keep_open do |out| connections << out out.callback { connections.delete(out) } end end 

On the client side:

 var es = new EventSource('/stream'); es.onmessage = function(e) { $('#chat').append(e.data + "\n") }; 

When I use the application directly, through http://localhost:9292/ everything works fine. The connection is permanent and all messages are sent to all clients.

However, when it passes through Nginx, http://chat.dev , the connection is dropped and the reconnection is triggered every second or so.

Nginx setup looks fine:

 upstream chat_dev_upstream { server 127.0.0.1:9292; } server { listen 80; server_name chat.dev; location / { proxy_pass http://chat_dev_upstream; proxy_buffering off; proxy_cache off; proxy_set_header Host $host; } } 

I tried keepalive 1024 in the upstream section, as well as proxy_set_header Connection keep-alive; in location .

Nothing helps: (

There are no persistent connections and messages that are not transmitted to any clients.

+58
ruby nginx sinatra
Dec 02
source share
3 answers

Your Nginx configuration is correct, you just skip a few lines.

Here is the "magic trio" creating an EventSource running through Nginx:

 proxy_set_header Connection ''; proxy_http_version 1.1; chunked_transfer_encoding off; 

Put them in the location section and it should work.

You may also need to add

 proxy_buffering off; proxy_cache off; 

This is not an official way to do this.

I ended this with trial and error + googling :)

+120
Dec 02
source share

Another option is to include the “X-Accel-Buffering" header with a no value in your response. Nginx specifically considers it, see http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering

+5
Oct 29 '15 at 12:20
source share

Do not write it from scratch yourself. Nginx is a great event-driven server and has modules that will handle SSE for you without compromising the performance of your upstream server.

Check out https://github.com/wandenberg/nginx-push-stream-module

How it works, the subscriber (browser using SSE) connects to Nginx, and the connection stops there. The publisher (your server for Nginx) will send POST to Nginx along the appropriate route, and at that moment Nginx will immediately go to the waiting EventSource listener in the browser.

This method is much more scalable than your ruby ​​web server handling these "long polls" of SSE connections.

+3
Feb 14 '15 at 20:42
source share



All Articles