Node.js: Server Sent Events のサンプル

実行結果
![node_server_sent_events.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/1fd4c76c-1ebf-9045-c2dd-3a4c8116f0d5.png)

```js:sse_server.js
// -------------------------------------------------------------------
//	sse_server.js
//
//					May/19/2021
//
// -------------------------------------------------------------------
var http = require("http")
var fs = require("fs")

const port = 1027


http.createServer(function (req, res) {
	const index = "./sse.html"
	var fileName
	var interval


console.log ("req.url = " + req.url)

  if (req.url === "/")
    fileName = index
  else
    fileName = "." + req.url

  if (fileName === "./stream") {
    res.writeHead(200, {"Content-Type":"text/event-stream", "Connection":"keep-alive"})

    res.write("retry: 10000\n")
    res.write("event: connecttime\n")
    res.write("data: " + (new Date()) + "\n\n")
    res.write("data: " + (new Date()) + "\n\n")

    interval = setInterval(function() {
      res.write("data: " + (new Date()) + "\n\n")
    }, 2000)
    req.connection.addListener("close", function () {
      clearInterval(interval)
    }, false)
  } else if (fileName === index) {
    fs.exists(fileName, function(exists) {
      if (exists) {
        fs.readFile(fileName, function(error, content) {
          if (error) {
            res.writeHead(500)
            res.end()
          } else {
            res.writeHead(200, {"Content-Type":"text/html"})
            res.end(content, "utf-8")
          }
        })
      } else {
        res.writeHead(404)
        res.end()
      }
    })
  } else {
    res.writeHead(404)
    res.end()
  }

}).listen (port, "127.0.0.1")

console.log("Server running at http://127.0.0.1:" + port + "/")

// -------------------------------------------------------------------
```

```html:sse.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
<script>
    window.addEventListener("load", function() {
      var button = document.getElementById("connect");
      var status = document.getElementById("status");
      var output = document.getElementById("output");
      var connectTime = document.getElementById("connecttime");
      var source;

      function connect() {
        source = new EventSource("stream");
        source.addEventListener("message", function(event) {
          output.textContent = event.data;
        }, false);

        source.addEventListener("connecttime", function(event) {
          connectTime.textContent = "Connection was last established at: " + event.data;
        }, false);

        source.addEventListener("open", function(event) {
          button.value = "Disconnect";
          button.onclick = function(event) {
            source.close();
            button.value = "Connect";
            button.onclick = connect;
            status.textContent = "Connection closed!";
          };
          status.textContent = "Connection open!";
        }, false);

        source.addEventListener("error", function(event) {
          if (event.target.readyState === EventSource.CLOSED) {
            source.close();
            status.textContent = "Connection closed!";
          } else if (event.target.readyState === EventSource.CONNECTING) {
            status.textContent = "Connection closed. Attempting to reconnect!";
          } else {
            status.textContent = "Connection closed. Unknown error!";
          }
        }, false);
      }

      if (!!window.EventSource) {
        connect();
      } else {
        button.style.display = "none";
        status.textContent = "Sorry, your browser doesn't support server-sent events";
      }
    }, false);
</script>
<title>Server-Sent Events Demo</title>
</head>
<body>
<input type="button" id="connect" value="Connect" /><br />
<span id="status">Connection closed!</span><br />
<span id="connecttime"></span><br />
<span id="output"></span>
<hr />
May/19/2021 AM 09:30<br />
</body>
</html>
```

サーバーの実行

```bash
node ./sse_server.js
```

ブラウザーで
http://127.0.0.1:1027/
にアクセス