Skip to content

Instantly share code, notes, and snippets.

@jordymeow
Created May 27, 2023 01:28
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jordymeow/4854992e7b4c510083c08ef8f5ca82c3 to your computer and use it in GitHub Desktop.
Save jordymeow/4854992e7b4c510083c08ef8f5ca82c3 to your computer and use it in GitHub Desktop.
SSE (Server-Sent Events) with PHP and JS / Streaming with PHP
<?php
// Various links
// https://serverfault.com/questions/488767/how-do-i-enable-php-s-flush-with-nginxphp-fpm
// https://stackoverflow.com/questions/72394213/nginx-configuration-for-server-sent-event
// https://serverfault.com/questions/801628/for-server-sent-events-sse-what-nginx-proxy-configuration-is-appropriate
// https://qiita.com/okumurakengo/items/cbe6b3717b95944083a1 (in Japanese)
// If '?SSE' is set, send Server-Sent events, otherwise we'll display the page.
if ( isset( $_GET['SSE'] ) ) {
// Set the headers for SSE.
header( 'Cache-Control: no-cache' );
header( 'Content-Type: text/event-stream' );
header( 'X-Accel-Buffering: no' ); // This is useful to disable buffering in nginx through headers.
// Push data to the browser every second.
ob_implicit_flush( true );
ob_end_flush();
for ( $i = 0; $i < 3; $i++ ) {
$data = "data: $i";
echo $data . "\n\n";
if ( ob_get_level() > 0 ) {
ob_flush();
}
flush();
error_log( $data );
sleep( 1 );
}
echo "data: Done!\n\n";
}
else {
?>
<h1>Stream / SSE</h1>
<p>
I build this code in order to experiment with <a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events">SSE</a> with PHP as it seems to be tricky to make it work. This idea is that the events below appear every one second, and not all at once.
</p>
<h2>Output:</h2>
<ul id="results"></ul>
<button onclick="window.location.reload();">Retry</button>
<script>
var url = window.location.href;
var source = new EventSource(url + "?SSE=true");
source.onmessage = function(event) {
if (event.data == 'Done!') {
source.close();
}
else {
document.getElementById("results").innerHTML += "<li>" + event.data + "</li>";
console.log(event);
}
};
source.onerror = function(event) {
console.error(event);
};
</script>
<?php
}
@jordymeow
Copy link
Author

As I am posting this, I couldn't make it work; I have tested this on WP Engine and a fresh install of WordPress on Local (by Flywheel), as most people are using a preset servers. I am looking for feedback to make this work.

@DeffoN0tSt3
Copy link

DeffoN0tSt3 commented May 29, 2023

on nginx server sent events should be configured else they wont be handled correctly. see proxy_buffering (must be off(or on in your case, it should be on, since you are using the header X-Accel-Buffering: no)) and gzip respectively. It's probably worth noting php also has settings that could potentially buffer the output. i shall try to test later in the week when i have time if you havent already rectified it :))

@jordymeow
Copy link
Author

The team behind Local (Flywheel) also shared with me how to make it work with Nginx and Local:

proxy_set_header Connection '';
proxy_http_version 1.1;

Works perfectly! You can find the whole thread here: https://community.localwp.com/t/enable-server-side-events-sse-streaming-with-php-by-default/37172/6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment