DEV Community

Cover image for Server-Sent Events (SSE) e como implementar
Mayderson Mello
Mayderson Mello

Posted on

Server-Sent Events (SSE) e como implementar

Server-Sent Events (SSE) é uma tecnologia que permite a comunicação unidirecional entre o servidor e o cliente em tempo real. SSE é uma alternativa aos WebSockets que oferece várias vantagens, como menor sobrecarga de rede e menor uso de recursos. Neste tutorial, iremos aprender como implementar SSE em Go e compará-lo com WebSockets.

O que é SSE?

SSE é um protocolo de comunicação baseado em HTTP que permite que o servidor envie eventos para o cliente. O cliente se inscreve em um fluxo SSE, que é uma conexão persistente entre o cliente e o servidor. O servidor envia eventos em formato de texto para o cliente, que é capaz de processá-los em tempo real. Os eventos podem ser nomeados e o payload pode ser em formato de texto ou JSON.

Como implementar?

O exemplo a seguir mostra como implementar SSE utilizando Golang, mas não se apegue a linguagem pois pode ser qualquer outra, basta definir os Headers corretos que você será capaz reproduzir.

Back-end (Golang)

package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        http.ServeFile(w, r, "index.html")
    })

    http.HandleFunc("/sse", func(w http.ResponseWriter, _ *http.Request) {
        w.Header().Set("Content-Type", "text/event-stream")
        w.Header().Set("Cache-Control", "no-cache")
        w.Header().Set("Connection", "keep-alive")

        messageCounter := 0

        for {
            someMessage := fmt.Sprintf("Message: %v", messageCounter)

            eventName := "event: myCustomEvent\n"
            payloadMessage := fmt.Sprintf("data: %s\n\n", someMessage)

            w.Write([]byte(eventName))
            w.Write([]byte(payloadMessage))

            time.Sleep(1 * time.Second)

            w.(http.Flusher).Flush()

            messageCounter++
        }
    })

    http.ListenAndServe(":3333", nil)
}
Enter fullscreen mode Exit fullscreen mode

A rota /sse define os cabeçalhos necessários para enviar eventos SSE. O cabeçalho Content-Type é definido como text/event-stream, Cache-Control é definido como no-cache para evitar o armazenamento em cache e Connection é definido como keep-alive para manter a conexão aberta. Em seguida, o servidor inicia um loop infinito para enviar eventos SSE. O evento é opcional e pode ser usado para especificar o tipo de evento que está sendo enviado. O payload contém os dados que estão sendo enviados.

O uso do \n é obrigatório, você pode observar que uso ele ao definir o nome do evento e payload da mensagem. O SSE vai conseguir interpretar quando essas informações foram definidas após essa quebra de linha, por fim, o \n adicional informa que acabou aquele evento.

Exemplo de como vai ficar no final após a interpretação:

event: myCustomEvent
data: Message: 1

event: myCustomEvent
data: Message: 2
Enter fullscreen mode Exit fullscreen mode

Front-end (HTML + JavaScript)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>SSE</title>
</head>
<body>
  <h1>SSE - Real Time Messages</h1>

  <ul id="messages"></ul>

  <script>
    const eventSource = new EventSource('/sse');

    eventSource.addEventListener('myCustomEvent', event => {
      const messagesElement = document.getElementById('messages');
      const li = document.createElement('li');

      li.innerText = event.data;

      messagesElement.appendChild(li);

      console.log(event);
    });
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

O código acima é muito simples, basicamente vamos estar recebendo as mensagens que o nosso Back-end vai mandar, e vamos adicionar elas em tela, somente isso.

A instância do EventSource, recebe a URL do endpoint SSE que o servidor está ouvindo (/sse neste caso). Isso estabelece uma conexão persistente entre o cliente e o servidor, permitindo que o servidor envie atualizações em tempo real para o cliente.

Em seguida, é adicionado um ouvinte de eventos para o evento personalizado myCustomEvent, que é enviado pelo servidor. Quando esse evento é recebido, uma nova linha de lista li é criada, contendo o texto da mensagem que foi enviada pelo servidor. A linha de lista é então adicionada ao elemento ul com o id messages, que é onde as mensagens são exibidas na página.

Front-end Preview

Front-end Network Tab

Vantagens e Desvantagens do SSE

SSE tem várias vantagens em relação aos WebSockets. A primeira é que ele é baseado em HTTP e usa a porta HTTP padrão (80), o que significa que ele pode passar por firewalls e proxies sem problemas. Além disso, o SSE requer menos sobrecarga de rede e recursos do servidor do que o WebSocket, porque apenas o servidor pode enviar dados. Isso significa que o servidor não precisa lidar com tantas conexões de saída e, portanto, pode lidar com mais conexões de entrada. Finalmente, o SSE é fácil de implementar, pois é baseado em HTTP e usa o mesmo modelo de programação.

No entanto, o SSE também tem algumas desvantagens. A primeira é que ele só suporta comunicação unidirecional (do servidor para o cliente), o que significa que o cliente não pode enviar dados para o servidor. Além disso, o SSE não é suportado por todos os navegadores e plataformas, o que significa que você precisará testar se o SSE funciona em todos os navegadores e plataformas que você deseja suportar.

Comparação SSE vs WebSockets

Embora SSE e WebSockets possam parecer semelhantes, eles têm algumas diferenças importantes. A principal diferença é que o WebSocket é bidirecional, o que significa que tanto o cliente quanto o servidor podem enviar dados. Isso torna o WebSocket mais adequado para aplicativos em tempo real que exigem interação bidirecional entre o cliente e o servidor, como jogos online ou aplicativos de bate-papo. O SSE, por outro lado, é mais adequado para aplicativos unidirecionais, como feeds de notícias ou atualizações de preços.

Além disso, o WebSocket usa um protocolo de comunicação personalizado que é implementado em um nível mais baixo do que o HTTP. Isso significa que o WebSocket é capaz de suportar recursos avançados, como multiplexação de canais, compressão de dados e autenticação do lado do servidor. O SSE, por outro lado, é implementado como um recurso do HTTP e, portanto, não pode usar esses recursos avançados.

Top comments (0)