How can I prevent nginx from buffering within PHP? - php

I am trying to push a page to the browser while it is being generated from a PHP script. I have no access to my hosting provider's nginx configuration but they have told me that they use nginx 1.8.1. In my phpinfo() output I can see
output_buffering 0 0
and the same script works as expected on my local PC.
This is my starting script:
<pre>
<?php
for ($i = 0; $i < 100; ++$i) {
print('<b>.</b>');
flush();
usleep(100000); // 0.1 second
}
?>
</pre>
I start getting output immediately on my local PC but I have to wait the full 10 seconds before I see anything when the page is accessed from my hosting.
These are the default response headers:
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 12 Apr 2016 12:32:05 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.4.45
Content-Encoding: gzip
If I add
<?php
header('X-Accel-Buffering: no');
I get
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 12 Apr 2016 12:35:10 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/5.4.45
Content-Encoding: gzip
<?php
header('X-Accel-Buffering: no');
header('Content-Encoding: identity');
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 12 Apr 2016 12:37:11 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 812
Connection: keep-alive
X-Powered-By: PHP/5.4.45
Content-Encoding: identity
Obviously, if the server knows the length of the content, it has waited for the script to finish before starting to send it to the browser.
These are the headers on my local machine:
HTTP/1.1 200 OK
Date: Tue, 12 Apr 2016 12:52:31 GMT
Server: Apache/2.4.7 (Win32) PHP/5.4.45 OpenSSL/1.0.1e
X-Powered-By: PHP/5.4.45
X-Accel-Buffering: no
Content-Encoding: identity
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
The X-Accel-Buffering header gets passed through because I am not running nginx locally.
Are there any other headers I can pass through from PHP to stop nginx from buffering the content? So far I've only found config options, which I don't have access to.

Related

Joomla Not Sending Custom Header

So I've got a server to server application. The PHP script on server 1, domain 1 sets a custom header in the page (Authorization: Bearer 123456789). The script on server 2, domain 2 uses get_headers() to read the headers.
It all works fine when the files are served natively. But when the script on server 1 is included in a Joomla module get_headers() doesn't retrieve the custom header.
In both cases, developer tools shows the custom header but also some different headers than returned by get_headers().
The code below uses JFactory to set the headers if Joomla is loaded but it is the same result using header(). Joomla just isn't passing the custom header.
I don't get it. Anyone have any idea what is going on here? Its not a SEF or htaccess issue.
<?php
// Server 1
if(!class_exists("JFactory")){ // no Joomla
header('Authorization: Bearer 123456789');
} else { // Joomla framework loaded
$app = JFactory::getApplication();
$app->setHeader('Authorization: ', 'Bearer 123456789');
$app->sendHeaders();
}
The code on server 2:
<?php
// Server 2
$headers = get_headers("http://server1.com/");
foreach($headers as $header) {
echo $header ."<br/>";
}
Output from get_headers() when served natively:
HTTP/1.1 200 OK
Date: Thu, 19 Jan 2017 12:44:35 GMT
Server: Apache
Authorization: Bearer 123456789
Content-Length: 0
Connection: close
Content-Type: text/html
Output from get_headers() when served by Joomla:
HTTP/1.1 200 OK
Date: Thu, 19 Jan 2017 12:45:49 GMT
Server: Apache
Set-Cookie: 3c460b3da9ecb202e794816b4144c6ff=ja7mn4b4njov98lsv76kk8pvu2; path=/; HttpOnly
Vary: Accept-Encoding
Content-Length: 1264
Connection: close
Content-Type: text/html
Native headers displayed by developer tools:
Authorization: Bearer 123456789
Date: Thu, 19 Jan 2017 13:07:32 GMT
Server: Apache
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
Content-Length: 0
Content-Type: text/html
200 OK
Joomla headers displayed by developer tools:
Pragma: no-cache
Date: Thu, 19 Jan 2017 12:19:24 GMT
Last-Modified: Thu, 19 Jan 2017 12:19:25 GMT
Server: Apache
Authorization: : Bearer 123456789
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
Content-Length: 76888
Expires: Wed, 17 Aug 2005 00:00:00 GMT
Remove double dot from setheader call :
$app = JFactory::getApplication();
$app->setHeader('Authorization', 'Bearer 123456789');
$app->sendHeaders();
Thanks for the suggestion Yoleth. I tested this and got the same result.
However I have found the problem. The Joomla site setting the header is using a component called Site Lock. This is similar to putting the site off line but has some nice features for developers.
Basically Site Lock was preventing the page being served and just returning the headers from the lock page (as it should). I don't know why I didn't see it earlier. Sometimes just can't see the forest for the trees!

php preg match get only last matched string

I need to get last HTTP headers. My string is:
HTTP/1.1 302 Moved Temporarily
Date: Sat, 30 Apr 2016 09:48:56 GMT
Server: Apache
X-Powered-By: PHP/5.5.34
Location: 2.php
Content-Length: 0
Content-Type: text/html
HTTP/1.1 302 Moved Temporarily
Date: Sat, 30 Apr 2016 09:48:57 GMT
Server: Apache
X-Powered-By: PHP/5.5.34
Location: 3.php
Content-Length: 0
Content-Type: text/html
HTTP/1.1 200 OK
Date: Sat, 30 Apr 2016 09:48:57 GMT
Server: Apache
X-Powered-By: PHP/5.5.34
Transfer-Encoding: chunked
Content-Type: text/html
But I need to get last headers. I tried to explode this string with \n\n but I couldn't get the result. Is it possible to do it with preg_match?
Gotcha!
I need to explode it with this code:
explode("\r\n\r\n", $header);
The solution using preg_split and array_pop functions:
// $headers is your initial string
$headers_splitted = preg_split("/\R{2}/", $headers);
print_r(array_pop($headers_splitted));
The output:
HTTP/1.1 200 OK
Date: Sat, 30 Apr 2016 09:48:57 GMT
Server: Apache
X-Powered-By: PHP/5.5.34
Transfer-Encoding: chunked
Content-Type: text/html

PHP Don't Let Apache Send Headers

I have installed php + apache. From one php file i send some headers using the header() function.
header("HTTP/1.1 200 OK");
header("Connection: Keep-Alive");
header("Content-Type: video/mp2t");
But i don't want apache to send its own headers. If i execute the PHP File i get these headers:
HTTP/1.1 200 OK
Date: Tue, 15 Apr 2014 10:26:57 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.4-14+deb7u8
Connection: Keep-Alive, Keep-Alive
Keep-Alive: timeout=5, max=100
Transfer-Encoding: chunked
Content-Type: video/mp2t
How can i prevent apache from sending its own headers?

Chrome totally ignoring Access-Control-Allow-Origin: * header

I am setting this with htaccess. I know it's being set properly because if I set another header:
Header set Access-Control-Allow-Origin2: *
Then chrome does see this. As soon as I remove the 2 however, chrome just completely ignores it. If I make my file a PHP file and put this in it:
<?php header("Access-Control-Allow-Origin: *"); ?>
Then it works.
Here are the response headers as reported by Chrome of the .htaccess method which I need to work and which does not:
HTTP/1.1 304 Not Modified
Date: Sun, 30 Mar 2014 00:13:06 GMT
Server: Apache/2.2.22 (Ubuntu)
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
ETag: "208f3-178a2-4f5c4f119cd34"
Vary: Accept-Encoding
Here are the response headers as reported by Chrome from the PHP method which for some reason does work:
HTTP/1.1 200 OK
Date: Sun, 30 Mar 2014 00:13:09 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.10
Access-Control-Allow-Origin: *
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 23
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: text/html
Again, I know the htaccess is setting the header, even if I go to an online service that checks reponse headers, I see this back:
HTTP/1.1 200 OK
Date: Sun, 30 Mar 2014 00:18:14 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Sat, 29 Mar 2014 20:48:34 GMT
ETag: "208f3-178a2-4f5c4f119cd34"
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Encoding: gzip
Access-Control-Allow-Origin: *
Content-Length: 33393
Content-Type: application/javascript

HTTP Headers difference - load page incrementally

I have an HTML page that shows a progress bar as it steps through a process. It uses flush() to send the data to the browser. I'm trying to get this to work in a Zend process which I'm short circuiting by specifically sending a header, content, then ending the process with an exit command.
The HTML page displays correctly (progress bar steps through being done). The Zend/PHP page only shows the finished page (not the steps). I'm assuming this is a header problem since the method (flush()) is identical.
In Chrome, the header for the HTML page comes up as:
HTTP/1.1 200 OK
Date: Fri, 27 Jul 2012 14:38:07 GMT
Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/0.9.8r DAV/2 PHP/5.3.2
X-Powered-By: PHP/5.3.2
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html
And the header for the Zend/PHP page comes up as:
HTTP/1.1 200 OK
Date: Fri, 27 Jul 2012 14:44:13 GMT
Server: Apache/2.2.16 (Unix) mod_ssl/2.2.16 OpenSSL/0.9.8r DAV/2 PHP/5.3.2
X-Powered-By: PHP/5.3.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-cache
Pragma: no-cache
Keep-Alive: timeout=5, max=98
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
The only header information I'm specifying in the PHP is:
header('Content-Type: text/html; charset=utf-8');
I'm using this code from this page: http://w3shaman.com/article/php-progress-bar-script
Any help would be appreciated. Thanks.
Call ob_flush() before you call flush() as Zend could have output buffering activated.
Mathieu had the fix. Adding ob_flush() before flush() in the Zend/PHP page fixed the problem. I'm not sure if Zend is activating output buffering as suggested or not.

Categories