mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-27 08:18:24 +03:00
Added new handled error for when request body is not valid JSON
This commit is contained in:
parent
921f303404
commit
812c5f4993
4 changed files with 90 additions and 12 deletions
29
module/Core/src/Exception/MalformedBodyException.php
Normal file
29
module/Core/src/Exception/MalformedBodyException.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shlinkio\Shlink\Core\Exception;
|
||||||
|
|
||||||
|
use Fig\Http\Message\StatusCodeInterface;
|
||||||
|
use JsonException;
|
||||||
|
use Mezzio\ProblemDetails\Exception\CommonProblemDetailsExceptionTrait;
|
||||||
|
use Mezzio\ProblemDetails\Exception\ProblemDetailsExceptionInterface;
|
||||||
|
|
||||||
|
use function Shlinkio\Shlink\Core\toProblemDetailsType;
|
||||||
|
|
||||||
|
class MalformedBodyException extends InvalidArgumentException implements ProblemDetailsExceptionInterface
|
||||||
|
{
|
||||||
|
use CommonProblemDetailsExceptionTrait;
|
||||||
|
|
||||||
|
public static function forInvalidJson(JsonException $prev): self
|
||||||
|
{
|
||||||
|
$e = new self('Provided request does not contain a valid JSON body.', previous: $prev);
|
||||||
|
|
||||||
|
$e->detail = $e->getMessage();
|
||||||
|
$e->title = 'Malformed request body';
|
||||||
|
$e->type = toProblemDetailsType('malformed-request-body');
|
||||||
|
$e->status = StatusCodeInterface::STATUS_BAD_REQUEST;
|
||||||
|
|
||||||
|
return $e;
|
||||||
|
}
|
||||||
|
}
|
27
module/Core/test/Exception/MalformedBodyExceptionTest.php
Normal file
27
module/Core/test/Exception/MalformedBodyExceptionTest.php
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ShlinkioTest\Shlink\Core\Exception;
|
||||||
|
|
||||||
|
use Fig\Http\Message\StatusCodeInterface;
|
||||||
|
use JsonException;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Shlinkio\Shlink\Core\Exception\MalformedBodyException;
|
||||||
|
|
||||||
|
class MalformedBodyExceptionTest extends TestCase
|
||||||
|
{
|
||||||
|
/** @test */
|
||||||
|
public function createsExpectedException(): void
|
||||||
|
{
|
||||||
|
$prev = new JsonException();
|
||||||
|
$e = MalformedBodyException::forInvalidJson($prev);
|
||||||
|
|
||||||
|
self::assertEquals($prev, $e->getPrevious());
|
||||||
|
self::assertEquals('Provided request does not contain a valid JSON body.', $e->getMessage());
|
||||||
|
self::assertEquals('Provided request does not contain a valid JSON body.', $e->getDetail());
|
||||||
|
self::assertEquals('Malformed request body', $e->getTitle());
|
||||||
|
self::assertEquals('https://shlink.io/api/error/malformed-request-body', $e->getType());
|
||||||
|
self::assertEquals(StatusCodeInterface::STATUS_BAD_REQUEST, $e->getStatus());
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,10 +5,12 @@ declare(strict_types=1);
|
||||||
namespace Shlinkio\Shlink\Rest\Middleware;
|
namespace Shlinkio\Shlink\Rest\Middleware;
|
||||||
|
|
||||||
use Fig\Http\Message\RequestMethodInterface;
|
use Fig\Http\Message\RequestMethodInterface;
|
||||||
|
use JsonException;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
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\Core\Exception\MalformedBodyException;
|
||||||
|
|
||||||
use function Functional\contains;
|
use function Functional\contains;
|
||||||
use function Shlinkio\Shlink\Common\json_decode;
|
use function Shlinkio\Shlink\Common\json_decode;
|
||||||
|
@ -42,7 +44,11 @@ class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterfac
|
||||||
return $request;
|
return $request;
|
||||||
}
|
}
|
||||||
|
|
||||||
$parsedJson = json_decode($rawBody);
|
try {
|
||||||
return $request->withParsedBody($parsedJson);
|
$parsedJson = json_decode($rawBody);
|
||||||
|
return $request->withParsedBody($parsedJson);
|
||||||
|
} catch (JsonException $e) {
|
||||||
|
throw MalformedBodyException::forInvalidJson($e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,12 @@ namespace ShlinkioTest\Shlink\Rest\Middleware;
|
||||||
use Laminas\Diactoros\Response;
|
use Laminas\Diactoros\Response;
|
||||||
use Laminas\Diactoros\ServerRequest;
|
use Laminas\Diactoros\ServerRequest;
|
||||||
use Laminas\Diactoros\Stream;
|
use Laminas\Diactoros\Stream;
|
||||||
|
use PHPUnit\Framework\Assert;
|
||||||
use PHPUnit\Framework\MockObject\MockObject;
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Shlinkio\Shlink\Core\Exception\MalformedBodyException;
|
||||||
use Shlinkio\Shlink\Rest\Middleware\BodyParserMiddleware;
|
use Shlinkio\Shlink\Rest\Middleware\BodyParserMiddleware;
|
||||||
|
|
||||||
class BodyParserMiddlewareTest extends TestCase
|
class BodyParserMiddlewareTest extends TestCase
|
||||||
|
@ -65,7 +67,6 @@ class BodyParserMiddlewareTest extends TestCase
|
||||||
/** @test */
|
/** @test */
|
||||||
public function jsonRequestsAreJsonDecoded(): void
|
public function jsonRequestsAreJsonDecoded(): void
|
||||||
{
|
{
|
||||||
$test = $this;
|
|
||||||
$body = new Stream('php://temp', 'wr');
|
$body = new Stream('php://temp', 'wr');
|
||||||
$body->write('{"foo": "bar", "bar": ["one", 5]}');
|
$body->write('{"foo": "bar", "bar": ["one", 5]}');
|
||||||
$request = (new ServerRequest())->withMethod('PUT')
|
$request = (new ServerRequest())->withMethod('PUT')
|
||||||
|
@ -73,16 +74,31 @@ class BodyParserMiddlewareTest extends TestCase
|
||||||
$handler = $this->createMock(RequestHandlerInterface::class);
|
$handler = $this->createMock(RequestHandlerInterface::class);
|
||||||
$handler->expects($this->once())->method('handle')->with(
|
$handler->expects($this->once())->method('handle')->with(
|
||||||
$this->isInstanceOf(ServerRequestInterface::class),
|
$this->isInstanceOf(ServerRequestInterface::class),
|
||||||
)->willReturnCallback(
|
)->willReturnCallback(function (ServerRequestInterface $req) {
|
||||||
function (ServerRequestInterface $req) use ($test) {
|
Assert::assertEquals([
|
||||||
$test->assertEquals([
|
'foo' => 'bar',
|
||||||
'foo' => 'bar',
|
'bar' => ['one', 5],
|
||||||
'bar' => ['one', 5],
|
], $req->getParsedBody());
|
||||||
], $req->getParsedBody());
|
|
||||||
|
|
||||||
return new Response();
|
return new Response();
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
$this->middleware->process($request, $handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function invalidBodyResultsInException(): void
|
||||||
|
{
|
||||||
|
$body = new Stream('php://temp', 'wr');
|
||||||
|
$body->write('{"foo": "bar", "bar": ["one');
|
||||||
|
$request = (new ServerRequest())->withMethod('PUT')
|
||||||
|
->withBody($body);
|
||||||
|
|
||||||
|
$handler = $this->createMock(RequestHandlerInterface::class);
|
||||||
|
$handler->expects($this->never())->method('handle');
|
||||||
|
|
||||||
|
$this->expectException(MalformedBodyException::class);
|
||||||
|
$this->expectExceptionMessage('Provided request does not contain a valid JSON body.');
|
||||||
|
|
||||||
$this->middleware->process($request, $handler);
|
$this->middleware->process($request, $handler);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue