cakephp: ExceptionRenderer doesn't handle custom status code as expected

(The original issue was reported from @nojimage)

This is a (multiple allowed):

  • bug
  • enhancement
  • feature-discussion (RFC)
  • CakePHP Version: 3.2.10 / 2.8.4
  • Platform and Target: non-related

What you did

Throw an exception with a custom error code.

$this->response->httpCodes([
   509 => 'Bandwidth Limit Exceeded',
]);

throw new HttpException('We are sorry', 509);

Expected Behavior

Get an error page with http code 509.

Actual Behavior

Get an error page with http code 500. Because ExceptionRenderer only allows HTTP codes within range 400 to 506:

$errorCode = $exception->getCode();
if ($errorCode >= 400 && $errorCode < 506) {
    $code = $errorCode;
}
return $code;

But I think it would be better to allow any status code if a caught exception is an instance of HttpException.

Solution

Change the above to the following:

$errorCode = $exception->getCode();
if ( $errorCode >= 400 && $errorCode < 506
    || $exception instanceof HttpException && $this->controller->response->httpCodes($errorCode)
) {
    $code = $errorCode;
}
return $code;

Do you think this change is backward compatible?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 2
  • Comments: 17 (17 by maintainers)

Commits related to this issue

Most upvoted comments

@dereuromark Sorry for my late reply. I totally forgot about this issue. Since cakephp/app#432 has been already merged, the original approach could work. I will re-think this issue when I have time.

I want to remove the $errorCode >= 400 && $errorCode < 506 check in the future release.

Why can’t we do that now?

@ADmad Thank you for your comment.

Would there be any drawbacks/problems if we just relaxed the check $errorCode < 506 to $errorCode < 600?

See #6094. To be honest, I want to remove the $errorCode >= 400 && $errorCode < 506 check in the future release.

Aside from that, Response class only allows status codes defined in the _statusCodes property. So we would need some way to register custom http codes into the Response object created in the ErrorRenderer.

@markstory After implementing this feature, I noticed another issue. Even if I registered a custom http code into the Response class via the httpCodes() method, they were not available in the ExceptionRenderer, because after an exception was thrown, the ExceptionRenderer would instantiate a different Response object here. Since ErrorController is not a subclass of AppController, I couldn’t register any custom http codes into the response object of the ErrorController by handling controller events. A workaround would be to create my AppErrorController. But it’s annoying little bit.

So what do you think about adding a new configuration to allow users to register custom http codes? The configuration and implementation would be like the following code:

// In config/app.php
[
    'App' => [
        'customHttpCodes' => [
            509 => 'Bandwidth Limit Exceeded',
        ]
    ]
]
// In src/Newtork/Response.php

public function __construct(array $options = [])
{
    ...

    $codes = Configure::read('App.customHttpCodes');
    if ($codes) {
        $this->httpCodes($codes);
    }
}