note 125304 deleted from function.fastcgi-finish-request by salathe
| From: | salathe@php.net | Date: | Thu, 27 Aug 2020 07:58:23 +0000 |
| Subject: | note 125304 deleted from function.fastcgi-finish-request by salathe | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-215030@lists.php.net to get a copy of this message | ||
Note Submitter: marcelotpcruz at gmail dot com
----
My previous code was not clean and fully tested, there was some workaround needed to make that
workable that I didn't post later.
But here comes a tested and nice class I wrote after searching a bit more about it that doesn't
close the connection, which according the information I looked around can affect keep alive.
Due credits to: https://stackoverflow.com/a/26892012
<?php
/**
* Output class
*
* Perform early "response flush" for users who can't rely on php
fastcgi_finish_request.
*/
class Output
{
private static $length_sent = 0;
private static bool $done = false;
const MIN_LENGTH_2_CLOSE_CONNECTION = 4 * 1024;
static function handle()
{
if (!ob_start(__CLASS__ . "::ob_chunked_gzhandler"))
self::startException();
self::sendHeader();
register_shutdown_function(__CLASS__ . "::close");
}
static function sendHeader()
{
// if (!headers_sent())
// throw new Exception("These should be sent!");
header('Transfer-Encoding: chunked');
}
static function startException()
{
throw new Exception("Ob start can't be started...");
}
/**
* close â Flushes all response data to the client
*
* This function flushes all response data to the client and finishes the request.
* This allows for time consuming tasks to be performed without leaving the connection to the
client open.
*
* control method must be called first any output is sent for this method to work.
*
* @return void
*/
static function close()
{
if (self::$done)
return;
ignore_user_abort(true);
if (session_id())
session_write_close();
self::$done = true;
if (ob_get_length())
ob_flush();
ob_end_clean();
self::$length_sent += 5;
// Terminating Chunk
echo "\x30\r\n\r\n";
if (self::$length_sent < self::MIN_LENGTH_2_CLOSE_CONNECTION)
echo str_pad("", self::MIN_LENGTH_2_CLOSE_CONNECTION - self::$length_sent,
"\r\n");
ob_flush();
flush();
}
static function ob_chunked_gzhandler($buffer, $phase)
{
$buffer = ob_gzhandler($buffer, $phase);
$length = strlen($buffer);
self::$length_sent += $length + 2;
return dechex($length) . "\r\n$buffer\r\n";
}
}
/**
* order of output and session_start doesn't matter
* Might as well be.
* session_start();
* Output::handle();
*/
Output::handle();
session_start();
var_dump($_SESSION);
$_SESSION["kk"] = "dfdfdf";
$_SESSION["xkcd"] = "dfdfdf";
echo "1";
echo "2\n";
Output::close();
sleep(10);
echo "Message user is not seeing...";
file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . 'bla.txt', "Yeah, A fully working
sample.");