Содержимое php-скрипта не сбрасывается

У меня есть этот код (он использует события на стороне сервера, но проблема в том, что он не работает):

<?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 } ?>

он работает локально на сервере wamp, но не на моем общем хостинге, у меня есть это в информации php:

Server API          CGI/FastCGI

Directive           Local Value    Master Value
output_buffering    4096           4096

и я не могу это изменить, я пытался добавить ob_start() в свой скрипт также ini_set('output_buffering', 0) и удалить ob_flush, но это не помогло.

Я также пытаюсь установить output_buffering на 0 в .user.ini для каталога, и информация о php показывает, что локальное значение равно 0, но события на стороне сервера по-прежнему не работают, я получаю все события сразу, а инструменты разработчика говорят (pending) с пустым типом, пока он не закончится через 10 секунд.

Инструменты разработчика

Кто-нибудь знает, как это исправить?

ИЗМЕНИТЬ:

Я снова пытаюсь запустить код (несколько лет спустя в Fedora/Linux), но результат тот же. Gzip не включается, но сообщения отображаются в конце.

Я пробовал:

  • добавить заголовок 'X-Accel-Buffering' => 'no'
  • также добавление echo "event:". $event ."\n";

безуспешно.

Я просматривал страницу событий PHP на стороне сервера, которая не загружалась при использовании цикла while, но решение не сработало, код выдает ту же ошибку, что и у OP (у него мало представителей, поэтому он, вероятно, не активен на SO), мой, по крайней мере, показывает события, но я прерываю цикл, его код имеет бесконечный цикл.

Это заголовки, отправленные сервером (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

То же самое происходит с простым кодом из http://demo.howopensource.com/sse/.

Мой php.ini имеет это:

$ grep -E 'user_ini|output_buffer|zlip.' /etc/php.ini | grep -v '^;'
user_ini.filename = ".user.ini"
output_buffering = 4096

Итак, я также попытался установить файл .user.init с помощью:

output_buffering = 0

а также

output_buffering = Off

но тоже не получилось. скрипт ждет возврата всего сразу. Код из этой статьи Streaming PHP — отключение буферизации вывода в PHP, Apache, Nginx и Varnish Если я использую $string_length = 4096;, даже phpinfo говорит, что буфер вывода отключен локально для этого каталога.

EDIT2:

Похоже, что флеш работает на моем общем хостинге, https://jcubic.pl/01.php?size=100, но я не могу протестировать его локально в Fedora, потому что флеш не работает.

Вот ссылка на мой локальный вывод phpinfo: https://jcubic.pl/phpinfo().html


person jcubic    schedule 03.12.2016    source источник
comment
на сервере есть сжатие (gzip или подобное)?   -  person francesco.venica    schedule 03.12.2016
comment
@kikko088 zlib.output_compression отключен   -  person jcubic    schedule 03.12.2016
comment
попробуйте добавить заголовок (X-Accel-Buffering: нет)   -  person francesco.venica    schedule 03.12.2016
comment
@ kikko088 не помог.   -  person jcubic    schedule 03.12.2016


Ответы (1)


Я включил сжатие gzip с помощью apache. Ответ на этот вопрос решил проблему:

Отключить сжатие Gzip в файле .htaccess

person jcubic    schedule 03.12.2016
comment
Это было давно, но кажется, что это решение не работает в Fedora так же, как мой виртуальный хостинг. На вкладке «Сеть» говорится, что gzip не включен, и он по-прежнему показывает все сообщения одновременно. - person jcubic; 17.09.2019