Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SSE Addon

Server-Sent Events (SSE) für REDAXO-Backend-Funktionen.

Status

Dieses AddOn ist aktuell ein Experiment. Es dient dazu, den Einsatz von Server-Sent Events (SSE) in REDAXO praxisnah zu demonstrieren und verschiedene Streaming-Szenarien im Backend zu testen.

Projekt-Repository:

https://github.com/FriendsOfREDAXO/sse

Enthaltene Bereiche

  • Fortschritt (sse_progress)
  • Chat (sse_chat, sse_chat_send, sse_chat_clear)
  • To-do (sse_todos)
  • Benutzerstatus (sse_users, sse_heartbeat)
  • Monitor (sse_monitor)
  • Medienverarbeitung (sse_media)
  • Symfony-Streams (sse_symfony, sse_symfony_old)
  • Logs (sse_logs)
  • Datenstream (sse_data)

Server-Voraussetzungen

Damit SSE stabil funktioniert, sollte der Server folgende Voraussetzungen erfüllen:

  • REDAXO ^5.18
  • PHP ^8.3
  • HTTP/1.1 oder HTTP/2 mit Keep-Alive
  • Reverse Proxy darf SSE-Antworten nicht puffern
  • Komprimierung für text/event-stream sollte deaktiviert sein
  • Ausreichende Timeouts (empfohlen: 300 bis 3600 Sekunden)

Wichtig bei SSE:

  • Content-Type muss text/event-stream sein
  • Antwort muss kontinuierlich gestreamt werden (kein Full-Response-Buffer)
  • Caching sollte für SSE deaktiviert sein

Konfiguration: Plesk mit NGINX als Proxy

Typisches Setup in Plesk: NGINX als Reverse Proxy vor Apache/PHP.

Kurzantwort auf die häufige Frage: Ja, primär konfigurierst du NGINX. Wenn Apache im Stack aktiv ist, solltest du zusätzlich Apache-Komprimierung für SSE deaktivieren und die PHP-Limits prüfen.

1) NGINX-Einstellungen in Plesk (Pflicht)

Pfad in Plesk:

  • Domains -> deine Domain -> Apache & nginx-Einstellungen
  • Feld: Zusätzliche nginx-Anweisungen

Dort ergänzen:

location = /redaxo/index.php {
	proxy_http_version 1.1;
	proxy_set_header Connection "";

	proxy_buffering off;
	proxy_request_buffering off;
	proxy_cache off;
	gzip off;

	proxy_read_timeout 3600s;
	proxy_send_timeout 3600s;

	add_header X-Accel-Buffering no;
}

2) Apache-Einstellungen in Plesk (empfohlen, wenn Apache aktiv)

Pfad in Plesk:

  • Domains -> deine Domain -> Apache & nginx-Einstellungen
  • Feld: Zusätzliche Apache-Anweisungen

Dort ergänzen:

<IfModule mod_headers.c>
	SetEnvIfExpr "%{REQUEST_URI} == '/redaxo/index.php' && %{QUERY_STRING} =~ /(^|&)rex-api-call=sse_/" is_sse_call=1
	Header always set Cache-Control "no-cache, no-transform" env=is_sse_call
</IfModule>

<IfModule mod_deflate.c>
	SetEnvIfExpr "%{REQUEST_URI} == '/redaxo/index.php' && %{QUERY_STRING} =~ /(^|&)rex-api-call=sse_/" no-gzip=1
</IfModule>

3) PHP-Einstellungen in Plesk prüfen (wichtig)

Pfad in Plesk:

  • Domains -> deine Domain -> PHP-Einstellungen

Prüfen/setzen:

  • max_execution_time ausreichend hoch (z. B. 300 bis 3600)
  • output_buffering möglichst aus oder klein
  • zlib.output_compression aus (für SSE)

4) Was ist wirklich nötig?

  • NGINX-Regeln sind bei Proxy-Setup zwingend.
  • Apache-Regeln sind bei aktivem Apache sehr sinnvoll, damit Events nicht komprimiert/gepuffert werden.
  • PHP-Limits entscheiden mit, ob Streams stabil offen bleiben.

Hinweis:

  • Diese Regel greift für Aufrufe über /redaxo/index.php.
  • Falls in der Umgebung weitere Proxy-Layer aktiv sind (CDN/WAF), dort ebenfalls Buffering und Caching für SSE deaktivieren.

Andere Webkonfigurationsoberflächen

cPanel/WHM

  • Je nach Stack (Apache-only, NGINX-Plugin, LiteSpeed) gibt es meist einen Bereich wie Include Editor, Custom Directives oder Additional NGINX directives.
  • Ziel ist immer gleich: Buffering aus, Cache aus, Timeouts hoch, keine Komprimierung für text/event-stream.

ISPConfig

  • In den Website-Einstellungen unter Nginx Directives bzw. Apache Directives entsprechende Regeln ergänzen.
  • Nach Änderungen Webserver-Konfiguration neu laden.

CloudPanel / HestiaCP / ähnliche Panels

  • Im vHost-Template oder in den zusätzlichen Domain-Direktiven die SSE-Regeln setzen.
  • Falls FastCGI-Buffering aktiv ist: für SSE deaktivieren.

Manuelle Konfiguration

NGINX (manuell)

location = /redaxo/index.php {
	proxy_http_version 1.1;
	proxy_set_header Connection "";
	proxy_buffering off;
	proxy_request_buffering off;
	proxy_cache off;
	gzip off;
	proxy_read_timeout 3600s;
	add_header X-Accel-Buffering no;
}

Apache (manuell)

Wenn Apache direkt ausliefert oder hinter einem Proxy läuft, sollten die Regeln auf SSE-Requests begrenzt werden:

<IfModule mod_headers.c>
	SetEnvIfExpr "%{REQUEST_URI} == '/redaxo/index.php' && %{QUERY_STRING} =~ /(^|&)rex-api-call=sse_/" is_sse_call=1
	Header always set Cache-Control "no-cache, no-transform" env=is_sse_call
	Header always set X-Accel-Buffering "no" env=is_sse_call
</IfModule>

<IfModule mod_deflate.c>
	SetEnvIfExpr "%{REQUEST_URI} == '/redaxo/index.php' && %{QUERY_STRING} =~ /(^|&)rex-api-call=sse_/" no-gzip=1
</IfModule>

Danach:

  • Konfiguration testen (nginx -t bzw. apachectl configtest)
  • Dienste neu laden/restarten
  • SSE-Endpoint im Browser testen und auf fortlaufende Events achten

Datenstream sse_data

Endpoint:

/redaxo/index.php?rex-api-call=sse_data

Unterstützte Parameter:

  • source: article_status, system_metrics, clock
  • interval: Sekundenintervall (1..30)
  • duration: Gesamtlaufzeit in Sekunden (10..3600)

Event-Typen:

  • init
  • data
  • complete

Beispiel:

/redaxo/index.php?rex-api-call=sse_data&source=article_status&interval=5&duration=600

Frontend-Nutzung von SSE

Die einfachste Nutzung im Frontend erfolgt mit EventSource.

Beispiel 1: Basis-Stream (Vanilla JavaScript)

<div id="sse-status">Verbinde...</div>
<pre id="sse-output"></pre>

<script>
const statusEl = document.getElementById('sse-status');
const outputEl = document.getElementById('sse-output');

const endpoint = '/redaxo/index.php?rex-api-call=sse_data&source=clock&interval=2&duration=120';
const stream = new EventSource(endpoint);

stream.onopen = () => {
	statusEl.textContent = 'Verbunden';
};

stream.onmessage = (event) => {
	outputEl.textContent += event.data + '\n';
};

stream.onerror = () => {
	statusEl.textContent = 'Verbindung unterbrochen - Reconnect läuft automatisch';
};
</script>

Hinweis: EventSource versucht bei Verbindungsabbrüchen automatisch einen Reconnect.

Beispiel 2: Eigene Event-Typen auswerten

Das AddOn liefert bei sse_data z. B. die Event-Typen init, data, complete.

<script>
const endpoint = '/redaxo/index.php?rex-api-call=sse_data&source=system_metrics&interval=5&duration=300';
const stream = new EventSource(endpoint);

stream.addEventListener('init', (event) => {
	console.log('Init:', JSON.parse(event.data));
});

stream.addEventListener('data', (event) => {
	const payload = JSON.parse(event.data);
	console.log('Daten:', payload);
});

stream.addEventListener('complete', (event) => {
	console.log('Fertig:', JSON.parse(event.data));
	stream.close();
});
</script>

Beispiel 3: URL mit Query-Parametern sauber bauen

const params = new URLSearchParams({
	'rex-api-call': 'sse_data',
	source: 'article_status',
	interval: '3',
	duration: '180'
});

const endpoint = '/redaxo/index.php?' + params.toString();
const stream = new EventSource(endpoint);

Beispiel 4: Ein div auf der Website live aktualisieren

Dieses Beispiel hält einen Statusbereich automatisch aktuell und zeigt den letzten Zeitstempel aus dem Stream.

<div id="live-box" style="padding:12px;border:1px solid #ddd;border-radius:8px;max-width:420px;">
	<strong>Live-Status:</strong>
	<div id="live-value">Warte auf Daten...</div>
	<small id="live-meta">Noch kein Update</small>
</div>

<script>
const valueEl = document.getElementById('live-value');
const metaEl = document.getElementById('live-meta');

const endpoint = '/redaxo/index.php?rex-api-call=sse_data&source=clock&interval=2&duration=1800';
const stream = new EventSource(endpoint);

stream.addEventListener('data', (event) => {
	try {
		const payload = JSON.parse(event.data);
		const value = payload.value ?? payload.time ?? event.data;
		valueEl.textContent = String(value);
		metaEl.textContent = 'Letztes Update: ' + new Date().toLocaleTimeString('de-DE');
	} catch (error) {
		valueEl.textContent = event.data;
		metaEl.textContent = 'Letztes Update: ' + new Date().toLocaleTimeString('de-DE');
	}
});

stream.onerror = () => {
	metaEl.textContent = 'Verbindung unterbrochen, Reconnect läuft ...';
};

window.addEventListener('beforeunload', () => {
	stream.close();
});
</script>

Best Practices im Frontend

  • Pro Browser-Tab nur so viele Streams öffnen wie nötig.
  • Streams beim Verlassen einer Seite schließen (stream.close()).
  • JSON robust parsen (try/catch), da auch Status- oder Fehlerevents auftreten können.
  • Bei Login-geschützten Endpoints sicherstellen, dass Session/Cookies vorhanden sind.

About

SSE DEMO für REDAXO

Resources

Code of conduct

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages