Belajar Echo - WebSocket, Streaming & SSE
Series/Belajar Echo/Episode 16
Episode 16 of 23

Belajar Echo - WebSocket, Streaming & SSE

Episode ini membuka komunikasi realtime: WebSocket dengan gorilla/websocket di dalam handler Echo, Server-Sent Events untuk notifikasi satu arah, streaming response untuk data besar, serta use case chat, notifikasi, dan long-lived connections.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Sebagian besar API bekerja satu arah: klien bertanya, server menjawab. Tapi ada dunia di mana server harus mendorong data kapan saja — chat, notifikasi, live price. Episode ini membuka komunikasi realtime di Echo dengan WebSocket dan Server-Sent Events.

Episode 16 ini membahas WebSocket dengan gorilla/websocket, Server-Sent Events untuk notifikasi satu arah, streaming response untuk data besar, serta use case chat dan long-lived connections.

WebSocket dalam Handler Echo

Upgrade Koneksi dengan gorilla/websocket

Echo tidak membawa WebSocket bawaan, tapi integrasinya mulus dengan gorilla/websocket. Handler melakukan upgrade dari HTTP biasa:

Install gorilla/websocket
go get github.com/gorilla/websocket
Handler WebSocket di Echo
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool { return true },
}
 
e.GET("/ws", func(c echo.Context) error {
	ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
	if err != nil {
		return err
	}
	defer ws.Close()
	for {
		msgType, msg, err := ws.ReadMessage()
		if err != nil {
			return err
		}
		if err := ws.WriteMessage(msgType, []byte("echo: "+string(msg))); err != nil {
			return err
		}
	}
})

Handler ini melakukan echo setiap pesan yang diterima klien. CheckOrigin menentukan asal yang boleh membuka koneksi — di production, validasi origin daripada mengembalikan true selalu.

Amankan CheckOrigin

Jangan pernah menerima semua origin di production. Batasi ke domain aplikasi:

CheckOrigin yang aman
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return r.Host == "app.example.com"
	},
}

Server-Sent Events

Push Satu Arah dengan SSE

SSE adalah cara sederhana server mengirim update ke klien tanpa memerlukan koneksi dua arah. Klien cukup membuka koneksi HTTP biasa:

Endpoint SSE untuk notifikasi
e.GET("/events", func(c echo.Context) error {
	h := c.Response().Header()
	h.Set(echo.HeaderContentType, "text/event-stream")
	h.Set(echo.HeaderCacheControl, "no-cache")
	h.Set(echo.HeaderConnection, "keep-alive")
 
	for i := 1; i <= 10; i++ {
		event := "event: notifikasi\n"
		event += "data: pesan ke-" + strconv.Itoa(i) + "\n\n"
		if _, err := c.Response().Write([]byte(event)); err != nil {
			return err
		}
		c.Response().Flush()
		time.Sleep(time.Second)
	}
	return nil
})

Pola SSE: tulis event dengan format data: <pesan> lalu panggil Flush agar data sampai ke klien segera. Format event harus diakhiri dua newline.

Streaming Response

Mengalirkan Data Besar

Kombinasikan dengan episode 7: c.Stream dan c.Response().Flush memungkinkan data besar dikirim bertahap. SSE hanyalah satu bentuk streaming; bentuk lain termasuk progress reporting dan pengiriman file besar:

Streaming dengan flush bertahap
e.GET("/stream", func(c echo.Context) error {
	c.Response().Header().Set(echo.HeaderContentType, "text/plain")
	for i := 1; i <= 100; i++ {
		if _, err := c.Response().Write([]byte("baris " + strconv.Itoa(i) + "\n")); err != nil {
			return err
		}
		c.Response().Flush()
	}
	return nil
})

Klien melihat baris pertama jauh sebelum server selesai menulis baris terakhir — tanpa streaming, seluruh respons harus menunggu selesai.

Use Case Nyata

Chat dan Long-Lived Connections

WebSocket unggul saat komunikasi dua arah dan latensi rendah adalah prioritas: chat, kolaborasi, game. Kelemahannya: koneksi dipegang terus, jadi setiap koneksi mengonsumsi resource dan perlu skala vertikal atau banyak instance dengan mechanisme broadcast terpusat.

SSE unggul untuk notifikasi satu arah — harga, alert, feed — karena lebih sederhana, memakai HTTP biasa yang melewati proxy dan load balancer dengan mudah.

Pola hub untuk broadcast
type Hub struct {
	clients map[*websocket.Conn]bool
	mu      sync.Mutex
}
 
func (h *Hub) broadcast(msg []byte) {
	h.mu.Lock()
	defer h.mu.Unlock()
	for client := range h.clients {
		client.WriteMessage(websocket.TextMessage, msg)
	}
}

Hub dengan mutex melacak semua koneksi aktif dan menyebarkan pesan ke seluruhnya. Ini adalah bentuk sederhana dari pola publish-subscribe.

Penutup

Episode 16 membuka komunikasi realtime: WebSocket dengan gorilla/websocket untuk dialog dua arah, SSE untuk push satu arah dengan format data:, streaming response dengan Flush, serta pola hub untuk broadcast ke banyak koneksi.

Inti yang harus dibawa pulang:

  • WebSocket dibangun dengan gorilla/websocket di handler Echo.
  • Validasi CheckOrigin di production, jangan terima semua origin.
  • SSE memakai text/event-stream dan format data: <pesan>.
  • Flush mengirim data segera sebelum buffer penuh.
  • WebSocket cocok untuk chat; SSE untuk notifikasi satu arah.
  • Long-lived connections butuh pola hub dan sinkronisasi mutex.
  • Setiap koneksi realtime mengonsumsi resource; rencanakan skalanya.

Di episode 17 selanjutnya kita akan membahas testing & benchmark — unit test handler dengan echo.New() dan httptest, menguji middleware, mocking service dengan antarmuka, serta benchmark testing.B untuk mengukur alokasi dan latensi route.

Belajar Echo - WebSocket, Streaming & SSE | Belajar Echo