Skip to content

Commit 96a0d4f

Browse files
committed
fix: output buffering
1 parent 3b3cfb5 commit 96a0d4f

5 files changed

Lines changed: 45 additions & 39 deletions

File tree

system/CodeIgniter.php

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
use Kint\Renderer\RichRenderer;
3737
use Locale;
3838
use LogicException;
39+
use Throwable;
3940

4041
/**
4142
* This class is the core of the framework, and will analyse the
@@ -164,6 +165,11 @@ class CodeIgniter
164165
*/
165166
protected bool $returnResponse = false;
166167

168+
/**
169+
* Application output buffering level
170+
*/
171+
protected int $bufferLevel;
172+
167173
/**
168174
* Constructor.
169175
*/
@@ -367,6 +373,7 @@ public function run(?RouteCollectionInterface $routes = null, bool $returnRespon
367373
try {
368374
return $this->handleRequest($routes, $cacheConfig, $returnResponse);
369375
} catch (RedirectException $e) {
376+
$this->outputBufferingEnd();
370377
$logger = Services::logger();
371378
$logger->info('REDIRECTED ROUTE at ' . $e->getMessage());
372379

@@ -389,6 +396,10 @@ public function run(?RouteCollectionInterface $routes = null, bool $returnRespon
389396
if ($return instanceof ResponseInterface) {
390397
return $return;
391398
}
399+
} catch (Throwable $e) {
400+
$this->outputBufferingEnd();
401+
402+
throw $e;
392403
}
393404
}
394405

@@ -810,7 +821,7 @@ protected function tryToRouteIt(?RouteCollectionInterface $routes = null)
810821
$this->benchmark->stop('bootstrap');
811822
$this->benchmark->start('routing');
812823

813-
ob_start();
824+
$this->outputBufferingStart();
814825

815826
$this->controller = $this->router->handle($path);
816827
$this->method = $this->router->methodName();
@@ -979,15 +990,8 @@ protected function display404errors(PageNotFoundException $e)
979990
// Display 404 Errors
980991
$this->response->setStatusCode($e->getCode());
981992

982-
if (ENVIRONMENT !== 'testing') {
983-
if (ob_get_level() > 0) {
984-
ob_end_flush(); // @codeCoverageIgnore
985-
}
986-
}
987-
// When testing, one is for phpunit, another is for test case.
988-
elseif (ob_get_level() > 2) {
989-
ob_end_flush(); // @codeCoverageIgnore
990-
}
993+
echo $this->outputBufferingEnd();
994+
flush();
991995

992996
// Throws new PageNotFoundException and remove exception message on production.
993997
throw PageNotFoundException::forPageNotFound(
@@ -1006,21 +1010,9 @@ protected function display404errors(PageNotFoundException $e)
10061010
*/
10071011
protected function gatherOutput(?Cache $cacheConfig = null, $returned = null)
10081012
{
1009-
$this->output = ob_get_contents();
1010-
// If buffering is not null.
1011-
// Clean (erase) the output buffer and turn off output buffering
1012-
if (ob_get_length()) {
1013-
ob_end_clean();
1014-
}
1013+
$this->output = $this->outputBufferingEnd();
10151014

10161015
if ($returned instanceof DownloadResponse) {
1017-
// Turn off output buffering completely, even if php.ini output_buffering is not off
1018-
if (ENVIRONMENT !== 'testing') {
1019-
while (ob_get_level() > 0) {
1020-
ob_end_clean();
1021-
}
1022-
}
1023-
10241016
$this->response = $returned;
10251017

10261018
return;
@@ -1150,4 +1142,22 @@ public function setContext(string $context)
11501142

11511143
return $this;
11521144
}
1145+
1146+
protected function outputBufferingStart(): void
1147+
{
1148+
$this->bufferLevel = ob_get_level();
1149+
ob_start();
1150+
}
1151+
1152+
protected function outputBufferingEnd(): string
1153+
{
1154+
$buffer = '';
1155+
1156+
while (ob_get_level() > $this->bufferLevel) {
1157+
$buffer = ob_get_contents();
1158+
ob_end_clean();
1159+
}
1160+
1161+
return $buffer;
1162+
}
11531163
}

system/Debug/BaseExceptionHandler.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,6 @@ protected function render(Throwable $exception, int $statusCode, $viewFile = nul
215215
exit(1);
216216
}
217217

218-
if (ob_get_level() > $this->obLevel + 1) {
219-
ob_end_clean();
220-
}
221-
222218
echo(function () use ($exception, $statusCode, $viewFile): string {
223219
$vars = $this->collectVars($exception, $statusCode);
224220
extract($vars, EXTR_SKIP);

system/Debug/Exceptions.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,6 @@ protected function render(Throwable $exception, int $statusCode)
296296
exit(1);
297297
}
298298

299-
if (ob_get_level() > $this->ob_level + 1) {
300-
ob_end_clean();
301-
}
302-
303299
echo(function () use ($exception, $statusCode, $viewFile): string {
304300
$vars = $this->collectVars($exception, $statusCode);
305301
extract($vars, EXTR_SKIP);

tests/system/CodeIgniterTest.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,6 @@ protected function tearDown(): void
5454
{
5555
parent::tearDown();
5656

57-
if (ob_get_level() > 1) {
58-
ob_end_clean();
59-
}
60-
6157
$this->resetServices();
6258
}
6359

@@ -73,6 +69,16 @@ public function testRunEmptyDefaultRoute()
7369
$this->assertStringContainsString('Welcome to CodeIgniter', $output);
7470
}
7571

72+
public function testOutputBufferingControl()
73+
{
74+
ob_start();
75+
$this->codeigniter->run();
76+
ob_get_clean();
77+
78+
// 1 phpunit output buffering level
79+
$this->assertSame(1, ob_get_level());
80+
}
81+
7682
public function testRunEmptyDefaultRouteReturnResponse()
7783
{
7884
$_SERVER['argv'] = ['index.php'];
@@ -828,10 +834,6 @@ public function testPageCacheWithCacheQueryString(
828834
$output = ob_get_clean();
829835

830836
$this->assertSame($string, $output);
831-
832-
if (ob_get_level() > 1) {
833-
ob_end_clean();
834-
}
835837
}
836838

837839
// Calculate how much cached items exist in the cache after the test requests

user_guide_src/source/changelogs/v4.4.0.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ Deprecations
142142
Bugs Fixed
143143
**********
144144

145+
- **Output Buffering:** Bug fix with output buffering.
146+
145147
See the repo's
146148
`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_
147149
for a complete list of bugs fixed.

0 commit comments

Comments
 (0)