SSE (Server-Sent Events) Tanıtımı
Server-Sent Events (SSE), istemcilerin bir HTTP bağlantısı aracılığıyla sunucudan otomatik olarak güncellemeler almasını sağlayan bir sunucu itme teknolojisidir. Sunucunun başlangıçtaki istemci bağlantısını oluşturduktan sonra nasıl veri transferini başlattığını açıklar. Genellikle, mesaj güncellemelerini veya sürekli veri akışlarını tarayıcı istemcilerine göndermek için kullanılır ve bu, JavaScript API'si olan EventSource aracılığıyla yerel çapraz tarayıcı akışlarını geliştirmeyi amaçlar. İstemciler, bu API'yi olay akışlarını almak için belirli bir URL'yi istemek için kullanabilir. HTML5'in bir parçası olarak, EventSource API, WHATWG tarafından standart hale getirilmiştir. SSE için medya türü text/event-stream'dir.
Not: SSE ve Websocket arasındaki en büyük fark, SSE'nin tek yönlü sunucudan istemciye mesaj itme olmasıdır, Websocket ise iki yönlü mesaj itme işlemidir. Bazı durumlarda, iş gereksinimleri karmaşık olmadığında, SSE'nin tek yönlü mesaj itmesi yeterli olabilir. Bu, ChatGPT AI sohbetlerinde kullanılan teknolojiye benzer.
Fiber SSE Örneği
package main
import (
"bufio"
"fmt"
"log"
"time"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/valyala/fasthttp"
)
// HTML istemcisini taklit et, burada, önyüzün gerçek iş senaryolarında, önyüzün bunu uygulayacağı şekilde backend itme mesajlarını JS'te almasının bir örneği bulunmaktadır.
var index = []byte(`<!DOCTYPE html>
<html>
<body>
<h1>SSE Mesajları</h1>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("http://127.0.0.1:3000/sse");
source.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
} else {
document.getElementById("result").innerHTML = "Üzgünüz, tarayıcınız sunucu-tarafından gönderilen olayları desteklemiyor...";
}
</script>
</body>
</html>
`)
func main() {
// Fiber örneği
app := fiber.New()
// Herhangi bir etki alanından erişime izin veren CORS kısıtlamaları
app.Use(cors.New(cors.Config{
AllowOrigins: "*",
AllowHeaders: "Cache-Control",
AllowCredentials: true,
}))
// / yoluna eriş, öncelikle önyüz sayfasını döndür, önyüzün arka uçtan SSE mesaj itme isteği yapmasına izin ver
app.Get("/", func(c *fiber.Ctx) error {
c.Response().Header.SetContentType(fiber.MIMETextHTMLCharsetUTF8)
return c.Status(fiber.StatusOK).Send(index)
})
// sse mesaj itme adresi
app.Get("/sse", func(c *fiber.Ctx) error {
// sse http başlığını ayarla, Content-Type'a dikkat et
c.Set("Content-Type", "text/event-stream")
c.Set("Cache-Control", "no-cache")
c.Set("Connection", "keep-alive")
c.Set("Transfer-Encoding", "chunked")
// Mesajları itme işlemini başlat
c.Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {
fmt.Println("YAZICI")
var i int
// İstemciye sürekli olarak mesaj itme işlemini taklit et
for {
i++
msg := fmt.Sprintf("%d - şu anki zaman: %v", i, time.Now())
// İstemciye mesaj itmek için yazıcı ve Fprintf fonksiyonunu kullan, gerçek iş senaryolarında, önyüz için JSON metni gönderilir
fmt.Fprintf(w, "data: Mesaj: %s\n\n", msg)
fmt.Println(msg)
// Çıktı verilerini istemciye gönder
err := w.Flush()
if err != nil {
// Web tarayıcısında sayfayı yenilemek, yeni bir SSE bağlantısı kuracaktır, ancak yalnızca sonuncusu yaşayacaktır, bu nedenle burada ölü bağlantılar kapatılmalıdır.
fmt.Printf("Sıfırlama sırasında hata oluştu: %v. Http bağlantısı kapatılıyor.\n", err)
break
}
time.Sleep(2 * time.Second)
}
}))
return nil
})
// Sunucuyu başlat
log.Fatal(app.Listen(":3000"))
}