Welcome Guest, Not a member yet? Register   Sign In
Custom Exception Handler Response Status Code
#1

Hi,
I'm trying to implement a Custom Exception Handler to allow me to use a custom twig based template error page.
This is really just for production side so all the front UI can stick with the same Twig based template system we are using.

The below code works fine but is returns a 200 status code rather than the relevant status code in the response.

How can I correct the status code?

Code:
class MyExceptionHandler extends BaseExceptionHandler implements ExceptionHandlerInterface
{
    protected ?string $viewPath = APPPATH . 'Views/errors/html/';

    public function handle(Throwable $exception, RequestInterface $request, ResponseInterface $response, int $statusCode, int $exitCode): void
    {
        $response->setStatusCode($statusCode);
        try {
            $this->twig($exception, $statusCode);
        } catch (\Exception $e) {
            $this->render($exception, $statusCode, $this->viewPath . ($statusCode == 404 ? 'error_404.php' : 'error.php'));
        }
        exit($exitCode);
    }

    protected function twig(Throwable $exception, int $statusCode): void
    {
        if(count(array_filter(config('Modules\CMS\Config\Twig')->paths, function($v) { return is_file($v . 'error.html.twig'); }))) {
            (new Twig(['config' => 'Modules\CMS\Config\Twig']))->display(
                'error.html.twig',
                [
                    'title'  => get_class($exception),
                    'type'    => get_class($exception),
                    'code'    => $statusCode,
                    'message' => $exception->getMessage(),
                ]
            );
        } else {
            throw new \Exception('Error template file not found. You must create a search template file error.html.twig', 500);
        }
    }
}

Thanks,

Luke
Reply
#2

Did you follow the steps in the user guide?
https://codeigniter4.github.io/CodeIgnit...n-handlers
Reply
#3

Hi Kenjis,

I did but it doesn't seem to show how to handle providing the response code.

I ended up looking at the system CodeIgniter\Debug\ExceptionHandler and lift some of the code from that.

Code:
        if ($request instanceof IncomingRequest) {
            try {
                $response->setStatusCode($statusCode);
            } catch (HTTPException $e) {
                // Workaround for invalid HTTP status code.
                $statusCode = 500;
                $response->setStatusCode($statusCode);
            }

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

With this added the status codes return correctly.
Reply
#4

I may have spoken to soon. 

I get the correct 404 response when throw:

Code:
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();

However, if I throw any other Exception I only ever get a 500 response regardless of what I pass as the 2nd parameter for the exception.

Code:
throw new \Exception('Forbidden!', 403);

As suggested in the guide I tried creating my own Exception class implementing the HTTPExceptionInterface. Like in the \CodeIgniter\Exceptions\PageNotFoundException I set the property $code to another status code (403 in my test) but still only 500 in returned by the ExceptionHandler.

Looking that ExceptionHandler handle method where is the $statusCode parameter passed in from?

If I call $exception->getCode(); from within the handle method I get the expected code 403 but the $statusCode parameter returns 500.

As a solution I have now just using $exception->getCode() to set the header status code. But I'm still wondering what the purpose of passing the separate $statusCode parameter is?
Reply




Theme © iAndrew 2016 - Forum software by © MyBB