mirror of
https://github.com/shlinkio/shlink.git
synced 2024-11-23 13:23:33 +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;
|
||||
|
||||
use Fig\Http\Message\RequestMethodInterface;
|
||||
use JsonException;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Shlinkio\Shlink\Core\Exception\MalformedBodyException;
|
||||
|
||||
use function Functional\contains;
|
||||
use function Shlinkio\Shlink\Common\json_decode;
|
||||
|
@ -42,7 +44,11 @@ class BodyParserMiddleware implements MiddlewareInterface, RequestMethodInterfac
|
|||
return $request;
|
||||
}
|
||||
|
||||
$parsedJson = json_decode($rawBody);
|
||||
return $request->withParsedBody($parsedJson);
|
||||
try {
|
||||
$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\ServerRequest;
|
||||
use Laminas\Diactoros\Stream;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Shlinkio\Shlink\Core\Exception\MalformedBodyException;
|
||||
use Shlinkio\Shlink\Rest\Middleware\BodyParserMiddleware;
|
||||
|
||||
class BodyParserMiddlewareTest extends TestCase
|
||||
|
@ -65,7 +67,6 @@ class BodyParserMiddlewareTest extends TestCase
|
|||
/** @test */
|
||||
public function jsonRequestsAreJsonDecoded(): void
|
||||
{
|
||||
$test = $this;
|
||||
$body = new Stream('php://temp', 'wr');
|
||||
$body->write('{"foo": "bar", "bar": ["one", 5]}');
|
||||
$request = (new ServerRequest())->withMethod('PUT')
|
||||
|
@ -73,16 +74,31 @@ class BodyParserMiddlewareTest extends TestCase
|
|||
$handler = $this->createMock(RequestHandlerInterface::class);
|
||||
$handler->expects($this->once())->method('handle')->with(
|
||||
$this->isInstanceOf(ServerRequestInterface::class),
|
||||
)->willReturnCallback(
|
||||
function (ServerRequestInterface $req) use ($test) {
|
||||
$test->assertEquals([
|
||||
'foo' => 'bar',
|
||||
'bar' => ['one', 5],
|
||||
], $req->getParsedBody());
|
||||
)->willReturnCallback(function (ServerRequestInterface $req) {
|
||||
Assert::assertEquals([
|
||||
'foo' => 'bar',
|
||||
'bar' => ['one', 5],
|
||||
], $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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue