I have this code (it use server side events but the problem is flush that don't work):
<?php
class Events {
function __construct($fn, $options=array()) {
$settings = array_merge(array(
'headers' => array(
'Content-Type' => 'text/event-stream',
'Cache-Control' => 'no-cache',
'Connection' => 'keep-alive'
),
'retry' => 2000
), $options);
foreach($settings['headers'] as $header => $value) {
header("$header: $value");
}
$lastId = intval(isset($_SERVER["HTTP_LAST_EVENT_ID"]) ? $_SERVER["HTTP_LAST_EVENT_ID"] : 0);
echo ":" . str_repeat(" ", 2048) . "\n";
echo "retry: " . $settings['retry'] . "\n";
$id = $lastId;
$i = 0;
foreach ($fn($id) as $value) {
echo "id:" . $id++ . "\n";
echo "data: " . $value . "\n\n";
ob_flush();
flush();
if ($i++ == 10) {
break;
}
}
}
}
if (isset($_SERVER['HTTP_ACCEPT']) && preg_match("%text/event-stream%", $_SERVER['HTTP_ACCEPT'])) {
new Events(function($id) {
while(true) {
$array = array("Foo", "Bar", "Baz", "Quux");
yield json_encode(array("message" => $array[array_rand($array)]));
sleep(1);
}
});
} else { ?><!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Leash</title>
<meta name="Description" content=""/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
var source = new EventSource("/EventSource.php");
source.addEventListener("message", function(message) {
console.log(JSON.parse(message.data).message);
});
</script>
<body>
<textarea></textarea>
</body>
</html><?php } ?>
it work locally on wamp server but it don't on my shared hosting, I have this in php info:
Server API CGI/FastCGI
Directive Local Value Master Value
output_buffering 4096 4096
and I'm not able to change it, I've try to add ob_start()
to my script also ini_set('output_buffering', 0)
and removing ob_flush
but that didn't help.
I've also try to set output_buffering to 0 in .user.ini for directory and the php info show that Local Value is 0 but server side events still don't work, I get all events all at once and the developer tools say (pending)
with empty type until it finish after 10 seconds.
Anybody know how to fix this?
EDIT:
I've again try to run the code (few years later on Fedora/Linux), but it give same results. Gzip is not turn on but the messages are showing at the end.
I've tried:
- add header
'X-Accel-Buffering' => 'no'
- also adding
echo "event:". $event ."\n";
without success.
I was looking at Server-side PHP event page not loading when using while loop but the solution didn't work, the code give same error as OP had (he don't have much rep so he's probably not active on SO), mine at least showing the events but I'm breaking the loop, his code have infinite loop.
This are headers sent by the server (Fedora):
Cache-Control: no-cache
Connection: keep-alive, Keep-Alive
Content-Type: text/event-stream;charset=UTF-8
Date: Tue, 17 Sep 2019 07:40:44 GMT
Keep-Alive: timeout=5, max=92
Server: Apache/2.4.41 (Fedora) OpenSSL/1.1.1c
Transfer-Encoding: chunked
X-Accel-Buffering: no
X-Powered-By: PHP/7.2.22
The same happen on simple code from http://demo.howopensource.com/sse/
My php.ini have this:
$ grep -E 'user_ini|output_buffer|zlip.' /etc/php.ini | grep -v '^;'
user_ini.filename = ".user.ini"
output_buffering = 4096
So I've also tried, set .user.init
file with:
output_buffering = 0
and
output_buffering = Off
but it also didn't worked. the script is waiting the return everything at once. Code from this article Streaming PHP - disabling output buffering in PHP, Apache, Nginx, and Varnish If I use $string_length = 4096;
even that phpinfo say that output buffer is disabled locally for this directory.
EDIT2:
IT seems that flush is working on my shared hosting, https://jcubic.pl/01.php?size=100 but I can't test it locally on Fedora because flush don't work.
Here is link to my local phpinfo output: https://jcubic.pl/phpinfo().html