Server sent events stopped work after enabling ssl on proxy

后端 未结 3 812
没有蜡笔的小新
没有蜡笔的小新 2021-02-06 13:28

I made web project, that based on Tomcat and Nginx in front of him.
Had to work hard to make it work without errors.
However, when I added ssl to nginx. Stopped working

相关标签:
3条回答
  • 2021-02-06 14:02

    For SSE to work properly, you must make sure nothing is getting cached or buffered: not in your script (e.g. in PHP we have the @ob_flush();@flush() idiom), not at your web server, and not at any intermediate proxies or firewalls.

    You say you commented out all the nginx commands to do with buffering, but commenting out means it will use the defaults. E.g. the default for proxy_buffering is on. I would suggest explictly specifying them to make sure all buffering and caching is switched off.

    proxy_buffering off;
    proxy_buffer_size 0;
    proxy_cache off;
    

    I would also consider explicitly setting the timeouts high, rather than commenting them out. The definition of "high" depends on your application. E.g. if it is always sending data every couple of seconds, the defaults will be fine. But if you are using SSE for irregular data, and there might sometimes be half an hour between messages, make sure the timeouts are more than half an hour.

    UPDATE: Apparently (see the comments) adding response.addHeader("X-Accel-Buffering", "no"); (i.e. to the server-side process, not to the proxy config) fixes the problem. This makes sense, as that was added specifically for SSE and similar HTTP streaming, see the nginx documentation. It does imply the above Nginx configuration should also work (the OP has reported that it does not). But, on the other hand, using a header to disable buffering on a per-connection basis feels like a better solution anyway.

    0 讨论(0)
  • 2021-02-06 14:02

    UPDATE: this was my answer before the OP gathered more information (in particular that if he waited long enough the data arrived, i.e. that it was a buffering issue: see my other answer). I've decided to leave it here as it might be useful troubleshooting ideas for someone else. (But if you disagree leave a comment or flag for deleting.)


    When planning "Data Push Apps with HTML5 SSE", using proxy servers was unfortunately the other side of where we drew the line; if you've read chapter 9 you'll know a seemingly simple standard can still get very complicated. So, I'm very interested to hear if and how you get this working.

    The first thing that comes to mind is you are using self-signed SSL certs. They won't work with SSE with Chrome. Ajax won't either. (See the bug report, but it was opened in 2011, so don't hold your breath.) However you said it works with Firefox, so this is unlikely to be it.

    The next thought is that you are using Access-Control-Allow-Origin:*, and Access-Control-Allow-Credentials:true, so I assume that means you need to for CORS (I.e. your html page origin and your SSE script origin are different in some way), and that cookies are involved. Are you setting { withCredentials: true } as the 2nd parameter to your EventSource constructor in your JavaScript? Even if so, be aware that Access-Control-Allow-Credentials:true does not work with Access-Control-Allow-Origin:*. You cannot specify *, and instead you have to explicitly say which origin is allowed.

    If that is the problem, you can use your server-side script to make the header dynamically, based on the client's origin. (The book shows code to do this in PHP.) If nginx can use environmental variables from the user's request, you should be able to do it there too.

    However, my understanding was that this would trip up with http too. I don't think it should just be an https problem. (If I'm wrong on that, let me know.)

    (Oh, if your working http SSE requests were coming from http://example.com, and are still coming from http://example.com, even though the SSE request is now going to https://example.com, then everything makes sense - you did not get CORS failures before because the origin was the same; now you do have a CORS problem, and you are not handling it correctly.)

    My third guess, is that the browser is sending a preflight OPTIONS request, but only doing it with https requests. (Preflight requests wildly from browser to browser, but it is not impossible that current versions of Chrome and Firefox behave the same way.) When you get an OPTIONS request you need to send back Access-Control-Allow-Headers: Last-Event-ID, Origin, X-Requested-With, Content-Type, Accept, Authorization. You also need to send back the Access-Control-Allow-Origin:* header.

    You can confirm or refute this third guess by packet sniffing to see what exactly is being sent back and forth. And if all the above ideas turned up nothing, you should do that anyway.

    0 讨论(0)
  • 2021-02-06 14:06

    Briefly, nginx detects if connection is alive with backend application and detection may not work correct in case of SSL, as described here

    http://mailman.nginx.org/pipermail/nginx/2013-March/038120.html

    0 讨论(0)
提交回复
热议问题