diff --git a/src/Symfony/Component/HttpKernel/Debug/ExceptionListener.php b/src/Symfony/Component/HttpKernel/Debug/ExceptionListener.php index d2e5fe52eec0..06a6befe50c2 100644 --- a/src/Symfony/Component/HttpKernel/Debug/ExceptionListener.php +++ b/src/Symfony/Component/HttpKernel/Debug/ExceptionListener.php @@ -16,6 +16,7 @@ use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Exception\FlattenException; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpFoundation\Request; /** @@ -63,6 +64,16 @@ public function onCoreException(GetResponseForExceptionEvent $event) 'format' => 0 === strncasecmp(PHP_SAPI, 'cli', 3) ? 'txt' : $request->getRequestFormat(), ); + $attributes += $exception instanceof HttpExceptionInterface ? array( + 'code' => $exception->getStatusCode(), + 'message' => $exception->getStatusMessage(), + 'headers' => $exception->getHeaders(), + ) : array( + 'code' => 500, + 'message' => 'Internal Server Error', + 'headers' => array(), + ); + $request = $request->duplicate(null, null, $attributes); try { diff --git a/src/Symfony/Component/HttpKernel/Exception/BaseHttpException.php b/src/Symfony/Component/HttpKernel/Exception/BaseHttpException.php new file mode 100644 index 000000000000..2a3150577625 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Exception/BaseHttpException.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * BaseHttpException. + * + * @author Kris Wallsmith + */ +abstract class BaseHttpException extends \RuntimeException implements HttpExceptionInterface +{ + protected $statusCode; + protected $statusMessage; + protected $headers; + + public function __construct($statusCode, $statusMessage, array $headers = array(), $message = null, $code = 0, \Exception $previous = null) + { + $this->statusCode = $statusCode; + $this->statusMessage = $statusMessage; + $this->headers = $headers; + + parent::__construct($message, 0, $previous); + } + + public function getStatusCode() + { + return $this->statusCode; + } + + public function getStatusMessage() + { + return $this->statusMessage; + } + + public function getHeaders() + { + return $this->headers; + } +} diff --git a/src/Symfony/Component/HttpKernel/Exception/HttpExceptionInterface.php b/src/Symfony/Component/HttpKernel/Exception/HttpExceptionInterface.php new file mode 100644 index 000000000000..6e09bd724466 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Exception/HttpExceptionInterface.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * Interface for HTTP error exceptions. + * + * @author Kris Wallsmith + */ +interface HttpExceptionInterface +{ + /** + * Returns the status code. + * + * @return integer An HTTP response status code + */ + function getStatusCode(); + + /** + * Return the status message. + * + * @return string An HTTP response status message + */ + function getStatusMessage(); + + /** + * Returns response headers. + * + * @return array Response headers + */ + function getHeaders(); +} diff --git a/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php new file mode 100644 index 000000000000..34da11d181ce --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * MethodNotAllowedHttpException. + * + * @author Kris Wallsmith + */ +class MethodNotAllowedHttpException extends BaseHttpException +{ + /** + * Constructor. + * + * WARNING: The status message will be sent as a response header + * regardless of debug mode. + * + * @param array $allow An array of allowed methods + * @param string $statusMessage The HTTP response status message + * @param string $message The internal exception message + * @param integer $code The internal exception code + * @param Exception $previous The previous exception + */ + public function __construct(array $allow, $statusMessage = 'Method Not Allowed', $message = null, $code = 0, \Exception $previous = null) + { + $headers = array('Allow' => strtoupper(implode(', ', $allow))); + + parent::__construct(405, $statusMessage, $headers, $message ?: $statusMessage, $code, $previous); + } +} diff --git a/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php b/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php index f7dfe71ede07..2cddc931ffd5 100644 --- a/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php @@ -16,10 +16,21 @@ * * @author Fabien Potencier */ -class NotFoundHttpException extends \RuntimeException +class NotFoundHttpException extends BaseHttpException { - public function __construct($message = 'Not Found', \Exception $previous = null) + /** + * Constructor. + * + * WARNING: The status message will be sent as a response header + * regardless of debug mode. + * + * @param string $statusMessage The HTTP response status message + * @param string $message The internal exception message + * @param integer $code The internal exception code + * @param Exception $previous The previous exception + */ + public function __construct($statusMessage = 'Not Found', $message = null, $code = 0, \Exception $previous = null) { - parent::__construct($message, 404, $previous); + parent::__construct(404, $statusMessage, array(), $message ?: $statusMessage, $code, $previous); } }