SSE (Server-Sent Events) — W3C стандард који омогућава серверу да шаље стриминг податке клијенту преко једне HTTP везе у једносмерном режиму. За разлику од WebSocket-а, SSE ради преко обичног HTTP-а и не захтева посебан протокол или библиотеку на страни клијента. Према спецификацији W3C HTML Living Standard (2025), EventSource API је подржан у свим савременим прегледачима, укључујући Chrome, Firefox, Safari и Edge.
Главно
SSE (Server-Sent Events) — технологија која омогућава веб серверу да шаље податке клијенту у било ком тренутку након успостављања везе. Стандардизована је од стране WHATWG-а као део HTML Living Standard-а и користи MIME тип text/event-stream. SSE подржава пренос текстуалних података са могућношћу навођења идентификатора поруке, типа догађаја и кашњења поновног повезивања.
За разлику од WebSocket-а, који захтева двосмерни протокол и upgrade захтев, SSE ради преко обичног HTTP-а. Сервер поставља заглавље Content-Type: text/event-stream, шаље податке у деловима и држи везу отвореном. Клијент прима податке преко прегледачког EventSource API-ја, који аутоматски парсира стрим и генерише догађаје.
Према подацима CanIUse (2025), EventSource API је подржан у 97.5% прегледача глобално. Није подржан у Internet Explorer-у и неким мобилним прегледачима (Samsung Internet до верзије 7.0). За ове случајеве постоје полифили који емулирају EventSource путем XHR streaming-а. SSE не ради са HTTP/1.1 pipelining-ом, али је потпуно компатибилан са HTTP/2 server push-ом.
SSE је предложен као део HTML5 спецификације 2009. године под називом Server-Sent DOM Events. Прва имплементација појавила се у Opera 9.0, затим у Firefox 6.0 (2011), Chrome 9.0 (2011) и Safari 5.0 (2010). 2015. године спецификација је издвојена у посебан одељак HTML Living Standard-а. Упркос десетогодишњој историји, SSE остаје мање популаран од WebSocket-а због своје једносмерне природе.
Механизам рада SSE је следећи: клијент креира инстанцу EventSource-а са URL-ом серверског ендпоинта. Прегледач шаље GET захтев са заглављем Accept: text/event-stream. Сервер одговара статусом 200 OK и заглављем Content-Type: text/event-stream, након чега почиње да шаље податке у формату event-stream. Веза остаје отворена док сервер не пошаље terminate сигнал или клијент не позове close().
На страни сервера подаци се шаљу у деловима (chunked transfer encoding). Сваки блок података је текстуална порука која се састоји од редова поља (event, data, id, retry). Сервер може слати поруке у било ком тренутку, што SSE чини идеалним за обавештења и ажурирања статуса. Веза не захтева сталну размену heartbeat пакета (као WebSocket), иако retry поље контролише учесталост поновног повезивања.
Према подацима тестова перформанси (2024), SSE обезбеђује пропусност до 10 000 порука у секунди по једној вези при величини поруке од 256 бајтова. На страни сервера, свака SSE веза троши приближно 5–10 KB меморије, што омогућава једном серверу да подржи 50 000+ истовремених веза при 1 GB RAM-а. Ово је значајно мање од WebSocket-а због недостатка бинарног протокола.
Формат text/event-stream — једноставан текстуални протокол где се свака порука састоји од именованих поља раздвојених знацима новог реда. Свако поље има формат „ИмеПоља: вредност“. Поруке су раздвојене са два знака новог реда (\n\n).
Подржана поља: event (тип догађаја, подразумевано message), data (низ података, може бити вишередни), id (последњи идентификатор догађаја, чува се у Last-Event-ID), retry (време поновног повезивања у милисекундама). Коментари почињу са двотачком (:) и парсер их игнорише, али се могу користити за heartbeat.
| Поље | Обавезно | Намена |
|---|---|---|
| event | Не | Тип догађаја (подразумевано message) |
| data | Да | Низ података поруке |
| id | Не | Идентификатор догађаја за Last-Event-ID |
| retry | Не | Кашњење поновног повезивања у ms |
: heartbeat comment
event: update
data: {"user": "Alice", "action": "typing"}
id: 1001
event: notification
data: {"type": "info", "text": "New version available"}
data: {"type": "action", "url": "/upgrade"}
retry: 3000
event: close
data: Session ended
EventSource API — уграђени интерфејс прегледача за пријем SSE. За креирање везе довољно је позвати конструктор са URL-ом ендпоинта. EventSource аутоматски успоставља везу, управља поновним повезивањем и парсира долазне поруке у JavaScript догађаје.
Догађаји EventSource-а: open (веза успостављена), message (примљена порука без навођења event), error (грешка у вези). За прилагођене догађаје (event: custom) може се користити addEventListener са именом догађаја. EventSource аутоматски шаље заглавље Last-Event-ID при поновном повезивању, што омогућава серверу да настави ток са прекинутог места.
Према документацији MDN (2025), EventSource подржава CORS и пренос credentials (withCredentials). За пренос прилагођених заглавља или тела захтева EventSource није погодан — потребна је ручна имплементација путем fetch + ReadableStream. EventSource не подржава бинарне податке — само текст и JSON.
const eventSource = new EventSource('/api/events/stream');
eventSource.addEventListener('open', () => {
console.log('SSE веза отворена');
});
eventSource.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
console.log('Примљено:', data);
renderUpdate(data);
});
eventSource.addEventListener('notification', (event) => {
const notification = JSON.parse(event.data);
showNotification(notification.text);
});
eventSource.addEventListener('error', (error) => {
console.error('SSE грешка:', error);
// Аутоматско поновно повезивање прегледача
});
// Затвори везу
eventSource.close();
SSE и WebSocket — различите технологије за комуникацију у реалном времену, свака са својим предностима. WebSocket је погодан за двосмерну размену података (четови, игре, заједничко уређивање), SSE — за једносмерне токове са сервера ка клијенту (обавештења, вести, тикери).
Кључна разлика — WebSocket захтева upgrade захтев са HTTP/1.1 на WebSocket протокол (ws://), што може бити блокирано од стране корпоративних проксија. SSE ради преко обичног HTTP-а, пролази кроз све проксије и не захтева посебну конфигурацију сервера. SSE је такође једноставнији за имплементацију — серверу није потребна додатна библиотека, довољно је правилно формирати HTTP одговор.
Према подацима упоредних тестова (2024), на једном серверском процесу SSE подржава 30–50% више веза од WebSocket-а због једноставнијег протокола. Међутим, latency SSE је већи (50–200 ms наспрам 10–50 ms код WebSocket-а) јер SSE користи chunked HTTP, а не потпуни двосмерни ток са бинарним оквирима.
| Карактеристика | SSE | WebSocket |
|---|---|---|
| Смер | Сервер → клијент | Двосмерни |
| Протокол | HTTP (text/event-stream) | ws:// / wss:// (RFC 6455) |
| Прегледачи | 97.5% (уграђени EventSource) | 97% (уграђени WebSocket) |
| Подаци | Само текст / JSON | Текст + бинарни (Blob, ArrayBuffer) |
| Обрада проксија | Пролази кроз све проксије | Захтева подешавање проксија |
| Поновно повезивање | Аутоматско (прегледач) | Ручна имплементација |
| Историја | Last-Event-ID | Нема уграђене историје |
Имплементација SSE на серверу не захтева библиотеке — довољно је поставити исправна HTTP заглавља и слати податке у формату text/event-stream. Погледајмо пример на Node.js коришћењем уграђеног http модула. Сервер поставља заглавља Content-Type и Cache-Control, затим шаље поруке сваких N секунди.
Према MDN Web Docs (2025), обавезна заглавља за SSE су: Content-Type: text/event-stream, Cache-Control: no-cache и Connection: keep-alive. Без Cache-Control-а прегледач може кеширати SSE ток, што ће довести до заустављања испоруке. Connection: keep-alive изричито указује прегледачу да држи везу отвореном.
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
let eventId = 0;
const interval = setInterval(() => {
eventId++;
res.write(`id: ${eventId}\n`);
res.write(`event: update\n`);
res.write(`data: {"време": "${new Date().toISOString()}", "id":${eventId}}\n\n`);
}, 2000);
req.on('close', () => {
clearInterval(interval);
});
}).listen(3000);
from flask import Response, Flask
import time
import json
app = Flask(__name__)
@app.route('/stream')
def stream():
def generate():
event_id = 0
while True:
event_id += 1
data = json.dumps(
{'ticker': 'AAPL', 'price': 150.25})
yield f'id: {event_id}\nevent: price\ndata: {data}\n\n'
time.sleep(1)
return Response(generate(),
mimetype='text/event-stream')
Употреба SSE у мобилним апликацијама је ограничена недостатком изворне имплементације EventSource-а за iOS и Android. На мобилним платформама SSE се имплементира преко спољних библиотека: на iOS-у — преко URLSession-а са NSURLProtocol-ом, на Android-у — преко OkHttp-а са SSE подршком (okhttp-sse). За React Native и Flutter доступни су пакети који емулирају EventSource.
На iOS-у изворна имплементација SSE је могућа преко URLSessionDataDelegate-а. При пријему података у методи urlSession(_:dataTask:didReceive:), апликација акумулира бафер и ручно парсира event-stream формат. Према блогу iOS развоја (2024), потрошња батерије при SSE-у на iOS-у је 40% нижа него при сталној WebSocket вези, због недостатка heartbeat пакета.
На Android-у OkHttp пружа класу EventSource.Factory за претплату на SSE токове. Android апликације могу користити SSE за обавештења када FCM није доступан или за синхронизацију података у позадини. SSE на Android-у добро ради са WorkManager-ом за дуготрајне позадинске задатке. Према документацији OkHttp (2025), okhttp-sse подржава аутоматско поновно повезивање са прилагођеним listener-ом.
Често постављана питања
SSE — једносмерни пренос (сервер → клијент) преко HTTP-а, не захтева библиотеке на клијенту. WebSocket — двосмерни пренос са бинарним протоколом. SSE је једноставнији за имплементацију, WebSocket је погодан за задатке где клијент такође шаље податке.
Не, SSE преноси само текстуалне податке. За бинарне податке (слике, аудио) потребно је Base64 кодирање, које повећава величину за 33%. За бинарне токове боље је користити WebSocket.
EventSource се аутоматски поново повезује при прекиду. Време кашњења се поставља преко retry поља у току (подразумевано 1000 ms). При поновном повезивању прегледач шаље заглавље Last-Event-ID, омогућавајући серверу да настави ток са прекинутог места.
Сваки прегледач има ограничење броја истовремених HTTP веза са једним доменом. За HTTP/1.1 — 6–8 веза по домену, за HTTP/2 — до 100. SSE користи једну везу, тако да нема конкуренције са другим захтевима.
SSE је погодан само за примање порука (долазне). За слање порука (одлазне) потребан је посебан HTTP захтев (POST). За потпуни чет погодније је користити WebSocket или Socket.IO са двосмерном комуникацијом у једној вези.
Завршни закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође