18

We have code similar to this:

<?php
    ob_implicit_flush(true);
    ob_end_flush();

    foreach ($arrayOfStrings as $string) {
        echo time_expensive_function($string);
    }
?>

In Apache, this would send each echo to the browser as it was output. In nginx/FastCGI however, this doesn't work due tot he way nginx works (by default).

Is it possible to make this work on nginx/FastCGI, and if so, how?

Leagsaidh Gordon
  • 1,531
  • 5
  • 17
  • 28

6 Answers6

32

First php has to correctly flush everything :

@ob_end_flush();
@flush();

Then, I found two working solutions:

1) Via Nginx configuration:

fastcgi_buffering off;

2) Via HTTP header in the php code

header('X-Accel-Buffering: no');
mad
  • 655
  • 6
  • 10
5

Easy solution:

fastcgi_keep_conn on; # < solution

proxy_buffering off;
gzip off;
3

I didn't want to have to turn off gzip for the whole server or a whole directory, just for a few scripts, in a few specific cases.

All you need is this before anything is echo'ed:

header('Content-Encoding: none;');

Then do the flush as normal:

ob_end_flush();
flush();

Nginx seems to pick up on the encoding having been turned off and doesn't gzip.

Redzarf
  • 2,177
  • 4
  • 25
  • 35
0

Add the flush() function in your loop:

foreach ($arrayOfStrings as $string) {
  echo time_expensive_function($string);
  flush();
}

It might work, but not necessarily on each iteration (there's some magic involved!)

Parallelis
  • 681
  • 3
  • 5
0

I needed both of those two lines at the beginning of my script:

header('X-Accel-Buffering: no');
ob_implicit_flush(true);

Each line alone would also work, combining them makes my browser getting the result from the server even faster. Cannot explain it, just experienced it.

My configuration is nginx with php-fpm.

n.r.
  • 726
  • 1
  • 4
  • 19