Created json_encode function which always maps to array and converts errors into exceptions

This commit is contained in:
Alejandro Celaya 2018-10-05 19:19:44 +02:00
parent e55dbef2fc
commit ff80f32f72
5 changed files with 28 additions and 16 deletions

View file

@ -3,8 +3,11 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Common; namespace Shlinkio\Shlink\Common;
use const JSON_ERROR_NONE;
use function getenv; use function getenv;
use function in_array; use function in_array;
use function json_last_error;
use function json_last_error_msg;
use function strtolower; use function strtolower;
use function trim; use function trim;
@ -42,7 +45,17 @@ function env($key, $default = null)
return trim($value); return trim($value);
} }
function contains($needle, array $haystack) function contains($needle, array $haystack): bool
{ {
return in_array($needle, $haystack, true); return in_array($needle, $haystack, true);
} }
function json_decode(string $json, int $depth = 512, int $options = 0): array
{
$data = \json_decode($json, true, $depth, $options);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new Exception\InvalidArgumentException('Error decoding JSON: ' . json_last_error_msg());
}
return $data;
}

View file

@ -3,10 +3,12 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Common\Exception; namespace Shlinkio\Shlink\Common\Exception;
use function sprintf;
class WrongIpException extends RuntimeException class WrongIpException extends RuntimeException
{ {
public static function fromIpAddress($ipAddress, \Throwable $prev = null): self public static function fromIpAddress($ipAddress, \Throwable $prev = null): self
{ {
return new self(\sprintf('Provided IP "%s" is invalid', $ipAddress), 0, $prev); return new self(sprintf('Provided IP "%s" is invalid', $ipAddress), 0, $prev);
} }
} }

View file

@ -5,7 +5,10 @@ namespace Shlinkio\Shlink\Common\Service;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\GuzzleException;
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
use Shlinkio\Shlink\Common\Exception\WrongIpException; use Shlinkio\Shlink\Common\Exception\WrongIpException;
use function Shlinkio\Shlink\Common\json_decode;
use function sprintf;
class IpApiLocationResolver implements IpLocationResolverInterface class IpApiLocationResolver implements IpLocationResolverInterface
{ {
@ -29,10 +32,12 @@ class IpApiLocationResolver implements IpLocationResolverInterface
public function resolveIpLocation(string $ipAddress): array public function resolveIpLocation(string $ipAddress): array
{ {
try { try {
$response = $this->httpClient->get(\sprintf(self::SERVICE_PATTERN, $ipAddress)); $response = $this->httpClient->get(sprintf(self::SERVICE_PATTERN, $ipAddress));
return $this->mapFields(\json_decode((string) $response->getBody(), true)); return $this->mapFields(json_decode((string) $response->getBody()));
} catch (GuzzleException $e) { } catch (GuzzleException $e) {
throw WrongIpException::fromIpAddress($ipAddress, $e); throw WrongIpException::fromIpAddress($ipAddress, $e);
} catch (InvalidArgumentException $e) {
throw new WrongIpException('IP-API returned invalid body while locating IP address', 0, $e);
} }
} }

View file

@ -8,15 +8,11 @@ use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Rest\Exception\RuntimeException;
use function array_shift; use function array_shift;
use function explode; use function explode;
use function json_decode;
use function json_last_error;
use function json_last_error_msg;
use function parse_str; use function parse_str;
use function Shlinkio\Shlink\Common\contains; use function Shlinkio\Shlink\Common\contains;
use function sprintf; use function Shlinkio\Shlink\Common\json_decode;
use function trim; use function trim;
class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterface class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterface
@ -67,7 +63,6 @@ class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterfac
/** /**
* @param Request $request * @param Request $request
* @return Request * @return Request
* @throws RuntimeException
*/ */
private function parseFromJson(Request $request): Request private function parseFromJson(Request $request): Request
{ {
@ -76,11 +71,7 @@ class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterfac
return $request; return $request;
} }
$parsedJson = json_decode($rawBody, true); $parsedJson = json_decode($rawBody);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException(sprintf('Error when parsing JSON request body: %s', json_last_error_msg()));
}
return $request->withParsedBody($parsedJson); return $request->withParsedBody($parsedJson);
} }

View file

@ -10,6 +10,7 @@ use Shlinkio\Shlink\Core\Entity\Tag;
use Shlinkio\Shlink\Core\Service\Tag\TagServiceInterface; use Shlinkio\Shlink\Core\Service\Tag\TagServiceInterface;
use Shlinkio\Shlink\Rest\Action\Tag\ListTagsAction; use Shlinkio\Shlink\Rest\Action\Tag\ListTagsAction;
use Zend\Diactoros\ServerRequestFactory; use Zend\Diactoros\ServerRequestFactory;
use function Shlinkio\Shlink\Common\json_decode;
class ListTagsActionTest extends TestCase class ListTagsActionTest extends TestCase
{ {
@ -42,7 +43,7 @@ class ListTagsActionTest extends TestCase
'tags' => [ 'tags' => [
'data' => ['foo', 'bar'], 'data' => ['foo', 'bar'],
], ],
], \json_decode((string) $resp->getBody(), true)); ], json_decode((string) $resp->getBody()));
$listTags->shouldHaveBeenCalled(); $listTags->shouldHaveBeenCalled();
} }
} }