JavaScript EventSource SSE not firing in browser

前端 未结 3 1322
不知归路
不知归路 2020-12-05 13:49

I have been developing a nodejs server to provide server-side-events for a new website I am developing in HTML5.

When I telnet to the server it works correctly, send

相关标签:
3条回答
  • 2020-12-05 14:20

    http://www.w3.org/TR/eventsource/#parsing-an-event-stream

    Since connections established to remote servers for such resources are expected to be long-lived, UAs should ensure that appropriate buffering is used. In particular, while line buffering with lines are defined to end with a single U+000A LINE FEED (LF) character is safe, block buffering or line buffering with different expected line endings can cause delays in event dispatch.

    Try to play with line endings ("\r\n" instead of "\n").

    http://www.w3.org/TR/eventsource/#notes

    Authors are also cautioned that HTTP chunking can have unexpected negative effects on the reliability of this protocol. Where possible, chunking should be disabled for serving event streams unless the rate of messages is high enough for this not to matter.

    0 讨论(0)
  • 2020-12-05 14:23

    I modified your server-side script, which 'seems' partly works for Chrome.
    But the connection break for every 2 broadcast & only 1 can be shown on client.

    Firefox works for 1st broadcast and stop by this error:

    Error: The connection to /sse was interrupted while the page was loading.

    And Chrome will try to reconnect and received 3rd broadcast.

    I think it's related to firewall setting too but can't explain why sometime will works.

    Note: For event listener of response (line 10), 'close' & 'end' have different result,
    You can try it and my result is [close: 1 success/2 broadcast] & [end: 1 success/8 broadcast]

    var http = require('http'), fs = require('fs'), requests = [];
    
    var server = http.Server(function(req, res) {
      var clientIP = req.socket.remoteAddress;
      var clientPort = req.socket.remotePort;
      if (req.url == '/sse') {
        var allClient="";for(var i=0;i<requests.length;i++){allClient+=requests[i].ip+":"+requests[i].port+";";}
        if(allClient.indexOf(clientIP+":"+clientPort)<0){
          requests.push({ip:clientIP, port:clientPort, res:res});
          res.on('close', function() {
            console.log("client " + clientIP + ":" + clientPort + " died");
            for(var i=requests.length -1; i>=0; i--) {
              if ((requests[i].ip == clientIP) && (requests[i].port == clientPort)) {
                requests.splice(i, 1);
              }
            }
          });
        }
      }else{
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write(fs.readFileSync('./test.html'));
        res.end();
      }
    });
    server.listen(80);
    
    setInterval(function test() {
      broadcast('poll', "test message");
    }, 500);
    
    var broadcastCount=0;
     function broadcast(rtype, msg) {
        if(!requests.length)return;
        broadcastCount++;
        var lines = msg.split("\n");
        for(var i = requests.length - 1; i >= 0; i--) {
            requests[i].res.writeHead(200, {
                'Content-Type': 'text/event-stream',
                'Cache-Control': 'no-cache',
                'Connection': 'keep-alive'
            });
            requests[i].res.write("event: " + rtype + "\n");
            for(var j = 0; j < lines.length; j++) {
                if(lines[j]) {
                    requests[i].res.write("data: " + lines[j] + "\n");
                }
            }
            requests[i].res.write("data: Count\: " + broadcastCount + "\n");
            requests[i].res.write("\n");
        }
        console.log("Broadcasted " + broadcastCount + " times to " + requests.length + " user(s).");
     }
    
    0 讨论(0)
  • 2020-12-05 14:26

    cracked it! :)

    Thanks to some help from Tom Kersten who helped me with testing. Turns out the code isnt the problem.

    Be warned.. if your client uses any kind of anti-virus software which intercepts web requests, it may cause problems here. In this case, Sophos Endpoint Security, which provides enterprise grade anti-virus and firewall protection has a feature called web protection. Within this features is an option to scan downloads; it seems that the SSE connection is treated as a download and thus not released to the browser until the connection is closed and the stream received to scan. Disabling this option cures the problem. I have submitted a bug report but other anti-virus systems may do the same.

    thanks for your suggestions and help everyone :)

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