Skip to content

Bug: CodeIgniter\Debug\Exceptions::exceptionHandler() sending header causes error if headers already sent #5679

@sclubricants

Description

@sclubricants

PHP Version

8.0

CodeIgniter4 Version

4.1.8

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Windows

Which server did you use?

apache

Database

No response

What happened?

If for some reason the application has already sent headers it causes another error in the exception handler and fails to properly handle this circumstance. This allows php to output error in production environment.

Steps to Reproduce

In a controller add the following lines:

echo 'Some output<br>';
flush();
setcookie("printer", 37); 
return;

Expected Output

It is expected to receive an error that you cannot modify headers because they are already sent.

However if in production or development environments the error is dumped by php as well as an additional similar error caused in the call to header() in CodeIgniter\Debug\Exceptions::exceptionHandler()

        if (! is_cli()) {
            $this->response->setStatusCode($statusCode);
            header(sprintf('HTTP/%s %s %s', $this->request->getProtocolVersion(), $this->response->getStatusCode(), $this->response->getReasonPhrase()), true, $statusCode);

            if (strpos($this->request->getHeaderLine('accept'), 'text/html') === false) {
                $this->respond(ENVIRONMENT === 'development' ? $this->collectVars($exception, $statusCode) : '', $statusCode)->send();

                exit($exitCode);
            }
        }

The screen as well as log files show:

CRITICAL - 2022-02-11 11:32:34 --> Cannot modify header information - headers already sent
#0 [internal function]: CodeIgniter\Debug\Exceptions->errorHandler(2, 'Cannot modify h...', 'C:\\xampp\\portal...', 16)
#1 C:\xampp\portal\app\Controllers\Admin\Test.php(16): setcookie('printer', '37')
#2 C:\xampp\portal\vendor\codeigniter4\framework\system\CodeIgniter.php(825): App\Controllers\Admin\Test->index()
#3 C:\xampp\portal\vendor\codeigniter4\framework\system\CodeIgniter.php(412): CodeIgniter\CodeIgniter->runController(Object(App\Controllers\Admin\Test))
#4 C:\xampp\portal\vendor\codeigniter4\framework\system\CodeIgniter.php(320): CodeIgniter\CodeIgniter->handleRequest(NULL, Object(Config\Cache), false)
#5 C:\xampp\portal\public\index.php(79): CodeIgniter\CodeIgniter->run()
#6 {main}
CRITICAL - 2022-02-11 11:32:34 --> Uncaught ErrorException: Cannot modify header information - headers already sent in C:\xampp\portal\vendor\codeigniter4\framework\system\Debug\Exceptions.php:115
Stack trace:
#0 [internal function]: CodeIgniter\Debug\Exceptions->errorHandler(2, 'Cannot modify h...', 'C:\\xampp\\portal...', 115)
#1 C:\xampp\portal\vendor\codeigniter4\framework\system\Debug\Exceptions.php(115): header('HTTP/1.1 500 In...', true, 500)
#2 [internal function]: CodeIgniter\Debug\Exceptions->exceptionHandler(Object(ErrorException))
#3 {main}
  thrown
#0 [internal function]: CodeIgniter\Debug\Exceptions->shutdownHandler()
#1 {main}

Anything else?

Its a messy situation I know.. Not sure the best way to handle it. If we suppress the second error by using @Header() at least the page will continue to render in development and in production will render error page instead of outputting errors.

        if (! is_cli()) {
            $this->response->setStatusCode($statusCode);
            @header(sprintf('HTTP/%s %s %s', $this->request->getProtocolVersion(), $this->response->getStatusCode(), $this->response->getReasonPhrase()), true, $statusCode);

            if (strpos($this->request->getHeaderLine('accept'), 'text/html') === false) {
                $this->respond(ENVIRONMENT === 'development' ? $this->collectVars($exception, $statusCode) : '', $statusCode)->send();

                exit($exitCode);
            }
        } 

Then our log outputs only the first error:

CRITICAL - 2022-02-11 11:52:34 --> Cannot modify header information - headers already sent
#0 [internal function]: CodeIgniter\Debug\Exceptions->errorHandler(2, 'Cannot modify h...', 'C:\\xampp\\portal...', 16)
#1 C:\xampp\portal\app\Controllers\Admin\Test.php(16): setcookie('printer', '37')
#2 C:\xampp\portal\vendor\codeigniter4\framework\system\CodeIgniter.php(825): App\Controllers\Admin\Test->index()
#3 C:\xampp\portal\vendor\codeigniter4\framework\system\CodeIgniter.php(412): CodeIgniter\CodeIgniter->runController(Object(App\Controllers\Admin\Test))
#4 C:\xampp\portal\vendor\codeigniter4\framework\system\CodeIgniter.php(320): CodeIgniter\CodeIgniter->handleRequest(NULL, Object(Config\Cache), false)
#5 C:\xampp\portal\public\index.php(79): CodeIgniter\CodeIgniter->run()
#6 {main}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugVerified issues on the current code behavior or pull requests that will fix them

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions