I am using SSE EventStream to stream large text to the client. My local Apache+PHP works great, however our NGINX+PHP servers are behaving oddly: There is an initial delay that is always ~10x of the word delay added below, and the stream comes in larger chunks rather than word-by-word, as expected. Also, the Transfer-encoding: chunked
and X-Accel-Buffering: no
are missing in response headers.
PHP code:
public function sse($delay = 50)
{
// Sample paragraph of text
$paragraph = "This is a sample paragraph of text. This is a sample paragraph of text. This is a sample paragraph of text. This is a sample paragraph of text. This is a sample paragraph of text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec elit sit amet a. This is a sample paragraph of text. This is a sample paragraph of text. This is a sample paragraph of text. This is a sample paragraph of text. This is a sample paragraph of text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec elit sit amet a";
// Split the paragraph into an array of words
$words = explode(' ', $paragraph);
// Set up headers for streaming
header('X-Accel-Buffering: no');
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
ini_set('zlib.output_compression', 0);
ini_set('implicit_flush', 1);
// This function discards the contents of the topmost output buffer and turns off this output buffering.
@ob_end_clean();
for ($i = 0; $i < ob_get_level(); $i++) { //for each open buffer
@ob_end_flush(); //close it
}
@ob_implicit_flush(1); //turn implicit flush on
// Emit "word" event for each word
$id = 1;
foreach ($words as $word) {
echo "id: $id".PHP_EOL;
echo "event: word".PHP_EOL;
echo "data: $word".PHP_EOL;
echo PHP_EOL;
@ob_flush();
flush();
usleep($delay*1000); // Delay between each word (in microseconds)
$id++;
}
@ob_flush();
flush();
}
Response Headers (missing Transfer-encoding: chunked
and X-Accel-Buffering: no
)
Cache-Control: no-cache;
Pragma: no-cache;
Content-Type: text/event-stream;charset=UTF-8;
...
Tried all the recommended settings below (together and separately).
NGINX Config
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding on;
proxy_buffering off;
proxy_cache off;
fastcgi_buffering off;
Only proxy_http_version seemed to make a difference. When not set, the whole result is returned at once. When set, there is streaming but with the aforementioned delay and larger chunks.