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). За тези случаи съществуват polyfill-и, които емулират 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 на сървърния endpoint. Браузърът изпраща GET заявка със заглавка Accept: text/event-stream. Сървърът отговаря със статус 200 OK и заглавка Content-Type: text/event-stream, след което започва да изпраща данни във формат event-stream. Връзката остава отворена, докато сървърът не изпрати сигнал за прекратяване или клиентът не извика 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 на endpoint-а. EventSource автоматично установява връзката, управлява повторното свързване и анализира входящите съобщения в JavaScript събития.
Събития на EventSource: open (връзката е установена), message (получено е съобщение без зададен event), error (грешка във връзката). За персонализирани събития (event: custom) може да се използва addEventListener с името на събитието. EventSource автоматично изпраща заглавка Last-Event-ID при повторно свързване, което позволява на сървъра да възобнови потока от прекъснатото място.
Според документацията на MDN (2025), EventSource поддържа CORS и предаване на идентификационни данни (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 поради по-опростен протокол. Въпреки това, латентността на 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също