Skip to content

Commit

Permalink
include exception description
Browse files Browse the repository at this point in the history
  • Loading branch information
juliangut committed Aug 5, 2017
1 parent 9774a45 commit 0f413a3
Show file tree
Hide file tree
Showing 16 changed files with 161 additions and 118 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Original Slim's error handling is bypassed by the HTTP exception manager forcing

Non HttpExceptions (for example an exception thrown by a third party library) will be automatically transformed into a 500 HttpException and alternatively you can use `HttpExceptionFactory` to throw HTTP exceptions yourself. Those exceptions will be handled to their corresponding handler depending on their "status code" or by the default handler in case no handler is defined for the specific status code

In the above example if you `throw HttpExceptionFactory::unauthorized()` during the execution of the application it'll be captured by the manager had handed over to "YourUnauthorizedRequestHandler" so you can format and return a proper custom response
In the above example if you `throw HttpExceptionFactory::unauthorized()` during the execution of the application it'll be captured by the manager hand handed over to "YourUnauthorizedRequestHandler" so you can format and return a proper custom response

### HTTP exceptions

Expand All @@ -73,9 +73,9 @@ The base of this error handling are the HTTP exceptions. This exceptions carry a
```php
use Jgut\Slim\Exception\HttpException;

$exceptionCode = 101; // Internal code
$exceptionCode = 1001; // Internal code
$httpStatusCode = 401; // Unauthorized
$exception = new HttpException('You shall not pass!', $exceptionCode, $httpStatusCode);
$exception = new HttpException('You shall not pass!', 'You do not have permission', $exceptionCode, $httpStatusCode);

$exception->getHttpStatusCode(); // 401 Unauthorized
```
Expand All @@ -91,9 +91,9 @@ $exception->getIdentifier();
In order to simplify HTTP exception creation and assure correct HTTP status code selection there are several shortcut creation methods

```php
throw HttpExceptionFactory::unauthorized('You shall not pass!', 101);
throw HttpExceptionFactory::notAcceptable('Throughput reached', 102);
throw HttpExceptionFactory::unprocessableEntity('Already exists', 103);
throw HttpExceptionFactory::unauthorized('You shall not pass!', 'You do not have permission', 1001);
throw HttpExceptionFactory::notAcceptable('Throughput reached', 'Too much', 1002);
throw HttpExceptionFactory::unprocessableEntity('Already exists', 'Entity already exists', 1030);
```

### Handlers
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
parameters:
ignoreErrors:
- '/Call to an undefined method Throwable::getIdentifier\(\)/'
- '/Call to an undefined method Throwable::getDescription\(\)/'
15 changes: 1 addition & 14 deletions src/Handler/AbstractHttpExceptionHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,7 @@ function (string $contentType) {
*
* @return array
*/
protected function getContentTypes(): array
{
return [
'text/plain',
'text/json',
'application/json',
'application/x-json',
'text/xml',
'application/xml',
'application/x-xml',
'text/html',
'application/xhtml+xml',
];
}
abstract protected function getContentTypes(): array;

/**
* Get error content.
Expand Down
42 changes: 30 additions & 12 deletions src/Handler/ExceptionHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@
*/
class ExceptionHandler extends AbstractHttpExceptionHandler
{
/**
* {@inheritdoc}
*/
protected function getContentTypes(): array
{
return [
'text/plain',
'text/json',
'application/json',
'application/x-json',
'text/xml',
'application/xml',
'application/x-xml',
'text/html',
'application/xhtml+xml',
];
}

/**
* {@inheritdoc}
*/
Expand All @@ -45,6 +63,18 @@ protected function getExceptionOutput(
return $this->getTextError($exception);
}

/**
* Get simple text formatted error.
*
* @param HttpException $exception
*
* @return string
*/
protected function getTextError(HttpException $exception): string
{
return sprintf('(%s) Application error', $exception->getIdentifier());
}

/**
* Get simple JSON formatted error.
*
Expand Down Expand Up @@ -95,16 +125,4 @@ protected function getHtmlError(HttpException $exception): string
$exception->getIdentifier()
);
}

/**
* Get simple text formatted error.
*
* @param HttpException $exception
*
* @return string
*/
protected function getTextError(HttpException $exception): string
{
return sprintf('(%s) Application error', $exception->getIdentifier());
}
}
48 changes: 12 additions & 36 deletions src/Handler/MethodNotAllowedHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,22 @@
namespace Jgut\Slim\Exception\Handler;

use Jgut\Slim\Exception\HttpException;
use Psr\Http\Message\ServerRequestInterface;

/**
* Method not allowed error handler.
*/
class MethodNotAllowedHandler extends AbstractHttpExceptionHandler
class MethodNotAllowedHandler extends ExceptionHandler
{
/**
* {@inheritdoc}
* Get simple text formatted error.
*
* @param HttpException $exception
*
* @return string
*/
protected function getExceptionOutput(
string $contentType,
HttpException $exception,
ServerRequestInterface $request
): string {
if (in_array($contentType, ['text/json', 'application/json', 'application/x-json'], true)) {
return $this->getJsonError($exception);
}

if (in_array($contentType, ['text/xml', 'application/xml', 'application/x-xml'], true)) {
return $this->getXmlError($exception);
}

if (in_array($contentType, ['text/html', 'application/xhtml+xml'], true)) {
return $this->getHtmlError($exception);
}

// text/plain
return $this->getTextError($exception);
protected function getTextError(HttpException $exception): string
{
return sprintf('(%s) %s', $exception->getIdentifier(), $exception->getMessage());
}

/**
Expand Down Expand Up @@ -92,20 +79,9 @@ protected function getHtmlError(HttpException $exception): string
'<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; ' .
'charset=utf-8"><title>Method not allowed</title><style>body{margin:0;padding:30px;font:12px/1.5 ' .
'Helvetica,Arial,Verdana,sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;' .
'}</style></head><body><h1>Method not allowed (Ref. %s)</h1></body></html>',
$exception->getIdentifier()
'}</style></head><body><h1>Method not allowed (Ref. %s)</h1><p>%s</p></body></html>',
$exception->getIdentifier(),
$exception->getMessage()
);
}

/**
* Get simple text formatted error.
*
* @param HttpException $exception
*
* @return string
*/
protected function getTextError(HttpException $exception): string
{
return sprintf('(%s) %s', $exception->getIdentifier(), $exception->getMessage());
}
}
53 changes: 13 additions & 40 deletions src/Handler/NotFoundHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,22 @@
namespace Jgut\Slim\Exception\Handler;

use Jgut\Slim\Exception\HttpException;
use Psr\Http\Message\ServerRequestInterface;

/**
* Route not found error handler.
*/
class NotFoundHandler extends AbstractHttpExceptionHandler
class NotFoundHandler extends ExceptionHandler
{
/**
* {@inheritdoc}
* Get simple text formatted error.
*
* @param HttpException $exception
*
* @return string
*/
protected function getExceptionOutput(
string $contentType,
HttpException $exception,
ServerRequestInterface $request
): string {
if (in_array($contentType, ['text/json', 'application/json', 'application/x-json'], true)) {
return $this->getJsonError($exception);
}

if (in_array($contentType, ['text/xml', 'application/xml', 'application/x-xml'], true)) {
return $this->getXmlError($exception);
}

if (in_array($contentType, ['text/html', 'application/xhtml+xml'], true)) {
return $this->getHtmlError($exception);
}

// text/plain
return $this->getTextError($exception);
protected function getTextError(HttpException $exception): string
{
return sprintf('(%s) %s', $exception->getIdentifier(), $exception->getMessage());
}

/**
Expand All @@ -54,10 +41,7 @@ protected function getExceptionOutput(
*/
protected function getJsonError(HttpException $exception): string
{
return sprintf(
'{"error":{"ref":"%s","message":"Not found"}}',
$exception->getIdentifier()
);
return sprintf('{"error":{"ref":"%s","message":"%s"}}', $exception->getIdentifier(), $exception->getMessage());
}

/**
Expand All @@ -71,9 +55,10 @@ protected function getXmlError(HttpException $exception): string
{
return sprintf(
'<?xml version="1.0" encoding="utf-8"?><root>' .
'<error><ref>%s</ref><message>Not found</message></error>' .
'<error><ref>%s</ref><message>%s</message></error>' .
'</root>',
$exception->getIdentifier()
$exception->getIdentifier(),
$exception->getMessage()
);
}

Expand All @@ -95,16 +80,4 @@ protected function getHtmlError(HttpException $exception): string
$exception->getIdentifier()
);
}

/**
* Get simple text formatted error.
*
* @param HttpException $exception
*
* @return string
*/
protected function getTextError(HttpException $exception): string
{
return sprintf('(%s) Not found', $exception->getIdentifier());
}
}
1 change: 1 addition & 0 deletions src/Handler/Whoops/DumperTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ protected function getExceptionData(Inspector $inspector, bool $addTrace = false
'id' => $exception->getIdentifier(),
'type' => get_class($exception),
'message' => $exception->getMessage(),
'description' => $exception->getDescription(),
];

if ($addTrace) {
Expand Down
30 changes: 27 additions & 3 deletions src/HttpException.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ class HttpException extends \RuntimeException
*/
protected $identifier;

/**
* Exception description.
*
* @var string
*/
protected $description;

/**
* HTTP status code.
*
Expand All @@ -38,20 +45,27 @@ class HttpException extends \RuntimeException
* Exception constructor.
*
* @param string $message
* @param string $description
* @param int $code
* @param int $httpStatusCode
* @param \Throwable|null $previous
*/
public function __construct(string $message, int $code, int $httpStatusCode, \Throwable $previous = null)
{
public function __construct(
string $message,
string $description,
int $code,
int $httpStatusCode,
\Throwable $previous = null
) {
parent::__construct($message, $code, $previous);

$this->identifier = ShortUuid::uuid4();
$this->description = $description;
$this->httpStatusCode = $httpStatusCode;
}

/**
* Get error unique identifier.
* Get exception unique identifier.
*
* @return string
*/
Expand All @@ -60,6 +74,16 @@ public function getIdentifier(): string
return $this->identifier;
}

/**
* Get exception description.
*
* @return string
*/
public function getDescription(): string
{
return $this->description;
}

/**
* Get HTTP status code.
*
Expand Down
Loading

0 comments on commit 0f413a3

Please sign in to comment.