-1

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.

Developer tools

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

jcubic
  • 61,973
  • 54
  • 229
  • 402

1 Answers1

1

I've had enabled gzip compression by apache answer to this question solved the issue:

Disable Gzip Compression in .htaccess file

Community
  • 1
  • 1
jcubic
  • 61,973
  • 54
  • 229
  • 402
  • It was long ago, but it seems that this solution don't work in Fedora same as my shared hosting. Network tab say that gzip is not turn on, and it's still showing messages all at once. – jcubic Sep 17 '19 at 07:10