YOGAE

TODO: FIXME:

Server-Sent Events

11 Jun 2019

SSE

SSE를 사용하여 통신 할 때 서버는 요청을 하지 않고도 필요할 때마다 데이터를 앱으로 푸시할 수 있습니다. 서버와 클라이언트 사이에 단일 단방향 채널을 엽니다. Server-Sent Events와 long-polling의 가장 큰 차이점은 SSE는 브라우저에서 직접 처리되므로 사용자는 메시지를 청취(구독) 해야 한다는 것입니다.

The EventSource interface is web content’s interface to server-sent events. An EventSource instance opens a persistent connection to an HTTP server, which sends eventsin text/event-stream format. The connection remains open until closed by calling EventSource.close().

Once the connection is opened, incoming messages from the server are delivered to your code in the form of message events.

SSE vs WebSockets

SSE는 단 방향통신만 가능하지만 WebSocket과 같은 API가 양방향 전이중 통신을 수행하기 위한 더 풍부한 프로토콜을 제공합니다.

SSE는 전통적인 HTTP를 통해 전송되므로 특별한 프로토콜이나 서버 구현이 필요하지 않습니다. 반면 WebSockets는 프로토콜을 처리하기 위해 전이중 연결과 새로운 웹 소켓 서버가 필요합니다.

SSE 구현

## client
var evtSource = new EventSource('sse.php');
var eventList = document.querySelector('ul');

evtSource.onmessage = function(e) {
  var newElement = document.createElement("li");

  newElement.textContent = "message: " + e.data;
  eventList.appendChild(newElement);
}

https://developer.mozilla.org/ko/docs/Web/API/EventSource

## server
var http = require('http');
var sys = require('sys');
var fs = require('fs');

http.createServer(function(req, res) {
  //debugHeaders(req);

  if (req.headers.accept && req.headers.accept == 'text/event-stream') {
    if (req.url == '/events') {
      sendSSE(req, res);
    } else {
      res.writeHead(404);
      res.end();
    }
  } else {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(fs.readFileSync(__dirname + '/sse-node.html'));
    res.end();
  }
}).listen(8000);

function sendSSE(req, res) {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
  });

  var id = (new Date()).toLocaleTimeString();

  // Sends a SSE every 5 seconds on a single connection.
  setInterval(function() {
    constructSSE(res, id, (new Date()).toLocaleTimeString());
  }, 5000);

  constructSSE(res, id, (new Date()).toLocaleTimeString());
}

function constructSSE(res, id, data) {
  res.write('id: ' + id + '\n');
  res.write("data: " + data + '\n\n');
}

function debugHeaders(req) {
  sys.puts('URL: ' + req.url);
  for (var key in req.headers) {
    sys.puts(key + ': ' + req.headers[key]);
  }
  sys.puts('\n\n');
}