PHP streaming works on localhost, but not online - php

I am trying to create a console for a script I'm working on, and make the progress stream in so the user can see it.
I read that having output_buffering disabled will not allow this to happen. So, I disabled it on my localhost server... I tried:
output_buffering = Off
output_buffering = 0
And commenting the line out although.
The console still works properly on localhost. Then I read that "gzip" won't allow this to happen. But gzip is enabled on both localhost and online server.
gzip compression enabled
zlib.output_compression is also Off
I even used diffchecker to change both the phpinfo(), and changed my localhost to be the exact same settings, yet it STILL works on localhost.
The only difference I can see is that my localhost is using CGI, and my server is using FastCGI.
Is this what's causing it not to work, and if not, what else would cause it to work on localhost, but not online?
Here's the basic code (it's being used with Ajax, but, I can't even make this basic version work):
<?php
ob_start();
echo "Starting...";
ob_flush();
flush();
echo "Finished with X";
ob_flush();
flush();
sleep(2);
echo "Finished with Y";
ob_flush();
flush();
sleep(2);
echo "Finished with Z";
ob_flush();
flush();
sleep(2);
?>

After spending forever reading threads, it seems that it was a problem with FastCGI and PHP. This code works though, even though I don't quite understand it.
if (ob_get_level() == 0) ob_start();
echo str_pad('',1024*64);
ob_flush();
flush();
usleep(500000);

Related

Switch from php-mod to php-fpm Output buffering problem

When using php-mod and fastcgi the code executes perfectly and every second i get an output but switching to php-fpm the code lags a few seconds before outputting depending on output size
Tried the following and combinations of
setting output buffer 0 in php ini
ob_implicit_flush
ob_start
ob_end_flush
header Content-Encoding = none
implicit_flush 1
ob_end_clean
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while( true ){
$time = date('r');
echo "retry:1000\r\n";
echo "data: ".$time;
echo "\r\n\r\n";
ob_flush();
flush();
sleep(1);
}
?>
This is for a production server and php-mod is not an option i also got it to work in Fastcgi with
FcgidOutputBufferSize 0
is there a way to make the code work on php-fpm so the output is send immediately as in php-mod and fastcgi ?
P.S Running : Ubuntu 18.04, Apache 2.4.29, PHP 7.2
After a few days i have discovered the only way to get this to work in php-fpm is to fill the output buffer. This is really inefficient ! Let me explain :
Say you are using Server-send events and your output buffer is 4096, you process every second even if you do not return anything you still send about 4Kb output to client where mod_php and fast-cgi sends only data when there is an output.
If anyone else has this problem this is my best solution : run main site on php-fpm ex. example.com and make a sub-domain ex. push.example.com and setup fast-cgi / php_mod[NOT RECOMMENDED PRODUCTION] on sub-domain now you can keep the connection open and process data without sending output to client.
PS. I saved Session variables in database so both domain and sub-domain can access it see https://github.com/dominicklee/PHP-MySQL-Sessions the other thing is to let sub-domain send CORS. in PHP add header('Access-Control-Allow-Origin: https://example.com');

ob_flush not working on new apache configuration

I recently migrated from Amazon Elastic Beanstalk to my own ubuntu 14.04 lts server. Everything ported smoothly except one page that uses ob_flush and proceeds to do processing. Here is that block of code:
<?php
//put string of page ----> $string
ob_end_clean();
header("Connection: close");
ignore_user_abort(true); // optional
ob_start();
echo ($string);
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // Strange behaviour, will not work
flush(); // Unless both are called !
session_write_close(); // Added a line suggested in the comment
// Do processing here
sleep(10);
//do stuff
echo "something";
I'm expecting the contents of $string to print, instead the contents of $string, and then "something" print. In this snippet, "something" would still print. I've disabling mod_pagespeed (which is currently enabled), and made sure gzip, and buffer output were set to off.
Here is my php.ini file (I have it offsite because it's unabridged and possible not relevant to the question). I also have a suspicion this may have to do with my apache configuration file which you can see Here. Finally, if this has anything to do with my issue, here is a link to my pagespeed configuration. When I call the function the error log shows no errors, additionally I have root access to the server. Thank you for helping me fix this issue!
Jake Sylvestre
I think that you are confusing ob_get_contents and ob_end_flush see: http://php.net/manual/en/function.ob-start.php.

ob_flush(), flush() not working from WAMP2 on Windows 7

This snippet:
ob_start();
for($i=0;$i<70;$i++)
{
echo 'printing...<br />';
ob_flush();
flush();
usleep(300000);
}
From this page: http://www.php.net/manual/en/function.flush.php#85382
Isn't working on WAMP2 (PHP 5.3.0, Apache 2.2.11) installed on Windows 7, browsing from http://localhost with IE 8, FF 6.0.2 and Chrome 13.
None of them worked. All the 'printing...' lines are just output in one instant batch when the page finished processing.
output_buffering in php.ini is set to 'On'.
Any ideas why it isn't working?
Several reasons why flush fails are discussed on the ob_flush() documentation page (eg interference with certain antivirus sw's, interference with zlib compression, ...). Worth reading.
You may need to close the session:
echo 'printing...<br />';
session_write_close();
ob_flush();
flush();

PHP script not echo'ing logs in real time - Was working on my other server

I wasn't sure how to title this thread, sorry.
I have a script that processes some logs and I echo a lot of debug information as the process goes. Since moving to the new server, it seems that the script hangs for 30 odd seconds, then spits out all the logging, then hangs again for 30 odd seconds and the process continues.
This is really odd behavior and I don't know where to start. Its like it isn't processing the file line by line but in blocks ...
PHP version is 5.1.6 on a CentOS running plesk. (My old CP was CPanel)
Any ideas?
EDIT: Simple example of my issue - Running this code:
for ($i=0; $i<100; $i++) {
echo "test $i";
sleep(1);
}
the script will hang for 100 seconds, then print out all the "test 1" ect. Sleep is required in my main script and on the other server just echoed the values in turn.
EDIT2: Have tried setting output_buffering = 0 and implicit_flush = On and didn't help.
You may have output_buffering On. Try to disable it first.
You can do it either in the php.ini file, in a .htaccess file if your server allows it, or use the following code at the beginning of your PHP script:
while (ob_get_level()) ob_end_clean();
Also, use flush() after each echo or print, and it should be all right!
Update:
You might also encounter other buffers that you cannot control from within PHP (web server, browser, ...), which is why you're still not seing anything. A workaround is to send some blank bytes after each print:
while (ob_get_level()) ob_end_clean();
for ($i=0; $i<100; $i++) {
echo "test $i";
echo str_repeat(' ', 256);
flush();
sleep(1);
}
However, while this example works for me on IE & Firefox, it does not work on Chrome!

PHP flushing output as soon as you call echo

I thought flush(); would work, at least from what Google/Stackoverflow tell me, but on my Windows WAMP (Windows, Apache, MySQL, PHP) system it doesn't work.
Is there some PHP setting I have to set to make flush() work?
Here's my code:
<?php
echo "Fun";
flush();
sleep(5);
echo "<br>Mo";
?>
The code just outputs all together when the script is done executing (after 5 seconds).. I don't want this, I want 'Fun' to show up right away, and then after 5 seconds 'Mo'.
I've tried other combinations of flush like ob_end_flush(); or ob_implicit_flush(true); but nothing is working. Any ideas?
So that's what I found out:
Flush would not work under Apache's mod_gzip or Nginx's gzip because, logically, it is gzipping the content, and to do that it must buffer content to gzip it. Any sort of web server gzipping would affect this. In short, at the server side, we need to disable gzip and decrease the fastcgi buffer size. So:
In php.ini:
. output_buffering = Off
. zlib.output_compression = Off
In nginx.conf:
. gzip off;
. proxy_buffering off;
Also have this lines at hand, specially if you don't have acces to php.ini:
#ini_set('zlib.output_compression',0);
#ini_set('implicit_flush',1);
#ob_end_clean();
set_time_limit(0);
Last, if you have it, coment the code bellow:
ob_start('ob_gzhandler');
ob_flush();
PHP test code:
ob_implicit_flush(1);
for($i=0; $i<10; $i++){
echo $i;
//this is for the buffer achieve the minimum size in order to flush data
echo str_repeat(' ',1024*64);
sleep(1);
}
The script works fine from CLI, displaying "Fun", waiting 5 secs before displaying "<br>Mo".
For a browser the results might be a bit different because:
The browser wont start rendering right away. Getting 3 bytes of data for HTML document isn't enough to do anything, so it'll most likely wait for a few more.
Implicit IO buffering on the lib level will most likely be active until a newline is received.
To work around 1) use text/plain content type for your test; 2) needs newlines, so do an echo "Fun\n"; and echo "<br>Mo\n"; Of course you wont be using text/plain for real HTML data.
If you're using CGI/FastCGI, forget it! These don't implement flush. The Webserver might have it's own buffer.
You can disable all output buffering in PHP with following command:
ob_implicit_flush();
If the problem persists, although you explicitly set
implicit_flush = yes
in your php.ini, you might also want to set
output_buffering = off
which did the trick in my case (after pulling my hair for 4+hrs)
Check your php.ini for output_buffering.
Maybe the problem is Apache here, which also may have buffers...

Categories