mirror of
https://github.com/shlinkio/shlink.git
synced 2026-02-28 04:03:12 +08:00
Created content based error handler which allows managing errors in a different way depending on the Accepted content type from the client
This commit is contained in:
22
module/Common/config/error-handler.config.php
Normal file
22
module/Common/config/error-handler.config.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
use Shlinkio\Shlink\Common\Expressive\ContentBasedErrorHandler;
|
||||
use Zend\Expressive\Container\TemplatedErrorHandlerFactory;
|
||||
use Zend\Stratigility\FinalHandler;
|
||||
|
||||
return [
|
||||
|
||||
'error_handler' => [
|
||||
'plugins' => [
|
||||
'invokables' => [
|
||||
'text/plain' => FinalHandler::class,
|
||||
],
|
||||
'factories' => [
|
||||
ContentBasedErrorHandler::DEFAULT_CONTENT => TemplatedErrorHandlerFactory::class,
|
||||
],
|
||||
'aliases' => [
|
||||
'application/xhtml+xml' => ContentBasedErrorHandler::DEFAULT_CONTENT,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
64
module/Common/src/Expressive/ContentBasedErrorHandler.php
Normal file
64
module/Common/src/Expressive/ContentBasedErrorHandler.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace Shlinkio\Shlink\Common\Expressive;
|
||||
|
||||
use Psr\Http\Message\RequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
|
||||
use Zend\ServiceManager\AbstractPluginManager;
|
||||
use Zend\ServiceManager\Exception\InvalidServiceException;
|
||||
|
||||
class ContentBasedErrorHandler extends AbstractPluginManager implements ErrorHandlerInterface
|
||||
{
|
||||
const DEFAULT_CONTENT = 'text/html';
|
||||
|
||||
public function validate($instance)
|
||||
{
|
||||
if (is_callable($instance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidServiceException(sprintf(
|
||||
'Only callables are valid plugins for "%s". "%s" provided',
|
||||
__CLASS__,
|
||||
is_object($instance) ? get_class($instance) : gettype($instance)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Final handler for an application.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|mixed $err
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, $err = null)
|
||||
{
|
||||
// Try to get an error handler for provided request accepted type
|
||||
$errorHandler = $this->resolveErrorHandlerFromAcceptHeader($request);
|
||||
return $errorHandler($request, $response, $err);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to resolve
|
||||
*
|
||||
* @param Request $request
|
||||
* @return callable
|
||||
*/
|
||||
protected function resolveErrorHandlerFromAcceptHeader(Request $request)
|
||||
{
|
||||
$accepts = $request->hasHeader('Accept') ? $request->getHeaderLine('Accept') : self::DEFAULT_CONTENT;
|
||||
$accepts = explode(',', $accepts);
|
||||
foreach ($accepts as $accept) {
|
||||
if (! $this->has($accept)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $this->get($accept);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'It wasn\'t possible to find an error handler for '
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace Shlinkio\Shlink\Common\Expressive;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Interop\Container\Exception\ContainerException;
|
||||
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
|
||||
use Zend\ServiceManager\Exception\ServiceNotFoundException;
|
||||
use Zend\ServiceManager\Factory\FactoryInterface;
|
||||
|
||||
class ContentBasedErrorHandlerFactory implements FactoryInterface
|
||||
{
|
||||
/**
|
||||
* Create an object
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
* @param string $requestedName
|
||||
* @param null|array $options
|
||||
* @return object
|
||||
* @throws ServiceNotFoundException if unable to resolve the service.
|
||||
* @throws ServiceNotCreatedException if an exception is raised when
|
||||
* creating a service.
|
||||
* @throws ContainerException if any other error occurs
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
||||
{
|
||||
$config = $container->get('config')['error_handler'];
|
||||
$plugins = isset($config['plugins']) ? $config['plugins'] : [];
|
||||
return new ContentBasedErrorHandler($container, $plugins);
|
||||
}
|
||||
}
|
||||
18
module/Common/src/Expressive/ErrorHandlerInterface.php
Normal file
18
module/Common/src/Expressive/ErrorHandlerInterface.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
namespace Shlinkio\Shlink\Common\Expressive;
|
||||
|
||||
use Psr\Http\Message\RequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
|
||||
interface ErrorHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Final handler for an application.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|mixed $err
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, $err = null);
|
||||
}
|
||||
18
module/Rest/config/error-handler.config.php
Normal file
18
module/Rest/config/error-handler.config.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
use Shlinkio\Shlink\Rest\Expressive\JsonErrorHandler;
|
||||
|
||||
return [
|
||||
|
||||
'error_handler' => [
|
||||
'plugins' => [
|
||||
'invokables' => [
|
||||
'application/json' => JsonErrorHandler::class,
|
||||
],
|
||||
'aliases' => [
|
||||
'application/x-json' => 'application/json',
|
||||
'text/json' => 'application/json',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
Binary file not shown.
@@ -1,9 +1,9 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Shlink 1.0\n"
|
||||
"POT-Creation-Date: 2016-07-21 16:39+0200\n"
|
||||
"PO-Revision-Date: 2016-07-21 16:40+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"POT-Creation-Date: 2016-07-27 08:53+0200\n"
|
||||
"PO-Revision-Date: 2016-07-27 08:53+0200\n"
|
||||
"Last-Translator: Alejandro Celaya <alejandro@alejandrocelaya.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: es_ES\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -52,9 +52,12 @@ msgid ""
|
||||
"Missing or invalid auth token provided. Perform a new authentication request "
|
||||
"and send provided token on every new request on the \"%s\" header"
|
||||
msgstr ""
|
||||
"No se ha proporcionado token de autenticación o este es inválido. Realia una "
|
||||
"nueva petición de autenticación y envía el token proporcionado en cada nueva "
|
||||
"petición en la cabecera \"%s\""
|
||||
"No se ha proporcionado token de autenticación o este es inválido. Realiza "
|
||||
"una nueva petición de autenticación y envía el token proporcionado en cada "
|
||||
"nueva petición en la cabecera \"%s\""
|
||||
|
||||
msgid "Requested route does not exist."
|
||||
msgstr "La ruta solicitada no existe."
|
||||
|
||||
#~ msgid "RestToken not found for token \"%s\""
|
||||
#~ msgstr "No se ha encontrado un RestToken para el token \"%s\""
|
||||
|
||||
39
module/Rest/src/Expressive/JsonErrorHandler.php
Normal file
39
module/Rest/src/Expressive/JsonErrorHandler.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
namespace Shlinkio\Shlink\Rest\Expressive;
|
||||
|
||||
use Psr\Http\Message\RequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Shlinkio\Shlink\Common\Expressive\ErrorHandlerInterface;
|
||||
use Zend\Diactoros\Response\JsonResponse;
|
||||
|
||||
class JsonErrorHandler implements ErrorHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Final handler for an application.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @param null|mixed $err
|
||||
* @return Response
|
||||
*/
|
||||
public function __invoke(Request $request, Response $response, $err = null)
|
||||
{
|
||||
$status = $response->getStatusCode();
|
||||
$responsePhrase = $status < 400 ? 'Internal Server Error' : $response->getReasonPhrase();
|
||||
$status = $status < 400 ? 500 : $status;
|
||||
|
||||
return new JsonResponse([
|
||||
'error' => $this->responsePhraseToCode($responsePhrase),
|
||||
'message' => $responsePhrase,
|
||||
], $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $responsePhrase
|
||||
* @return string
|
||||
*/
|
||||
protected function responsePhraseToCode($responsePhrase)
|
||||
{
|
||||
return strtoupper(str_replace(' ', '_', $responsePhrase));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user