diff --git a/CHANGELOG.md b/CHANGELOG.md index add06f8..ed8147b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Data Transfer Object classes generation from swagger spec +## [0.0.8] - 2020-06-25 +### Added +- fig/http-message-util package dependency (StatusCodeInterface is using) + +### Fixed +- Respond with 400 instead 500 on invalid json, handle it with BodyParser middleware +- Set type in DTO\AbstractResourceObject + ## [0.0.7] - 2020-06-12 ### Added - Relationships support in DTO classes @@ -54,7 +62,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - FastRoute Dispatcher generation from swagger operationIds -[Unreleased]: https://github.com/FreeElephants/json-api-php-toolkit/compare/0.0.7...HEAD +[Unreleased]: https://github.com/FreeElephants/json-api-php-toolkit/compare/0.0.8...HEAD +[0.0.8]: https://github.com/FreeElephants/json-api-php-toolkit/compare/0.0.7...0.0.8 [0.0.7]: https://github.com/FreeElephants/json-api-php-toolkit/compare/0.0.6...0.0.7 [0.0.6]: https://github.com/FreeElephants/json-api-php-toolkit/compare/0.0.5...0.0.6 [0.0.5]: https://github.com/FreeElephants/json-api-php-toolkit/compare/0.0.4...0.0.5 diff --git a/composer.json b/composer.json index 3b6f850..114d8bc 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,7 @@ "ext-intl": "*", "ext-json": "*", "cebe/php-openapi": "^1.4", + "fig/http-message-util": "^1.1", "free-elephants/i18n": "^0.0.1", "laminas/laminas-stratigility": "^3.2", "neomerx/json-api": "^4.0", diff --git a/src/FreeElephants/JsonApiToolkit/DTO/AbstractResourceObject.php b/src/FreeElephants/JsonApiToolkit/DTO/AbstractResourceObject.php index 5885748..c087bca 100644 --- a/src/FreeElephants/JsonApiToolkit/DTO/AbstractResourceObject.php +++ b/src/FreeElephants/JsonApiToolkit/DTO/AbstractResourceObject.php @@ -14,6 +14,7 @@ class AbstractResourceObject public function __construct(array $data) { $this->id = $data['id']; + $this->type = $data['type']; $concreteClass = new \ReflectionClass($this); diff --git a/src/FreeElephants/JsonApiToolkit/Middleware/BodyParser.php b/src/FreeElephants/JsonApiToolkit/Middleware/BodyParser.php index 6e65793..7a83384 100644 --- a/src/FreeElephants/JsonApiToolkit/Middleware/BodyParser.php +++ b/src/FreeElephants/JsonApiToolkit/Middleware/BodyParser.php @@ -2,6 +2,8 @@ namespace FreeElephants\JsonApiToolkit\Middleware; +use Fig\Http\Message\StatusCodeInterface; +use FreeElephants\JsonApiToolkit\Psr\JsonApiResponseFactory; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; @@ -9,10 +11,28 @@ class BodyParser implements MiddlewareInterface { + private JsonApiResponseFactory $responseFactory; + + public function __construct(JsonApiResponseFactory $responseFactory) + { + $this->responseFactory = $responseFactory; + } + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { $request->getBody()->rewind(); - $request = $request->withParsedBody(json_decode($request->getBody()->getContents(), true)); + + $decodedBody = json_decode($request->getBody()->getContents(), true); + + if ($decodedBody === null && json_last_error() !== JSON_ERROR_NONE) { + return $this->responseFactory->createSingleErrorResponse( + 'Provided json is invalid', + StatusCodeInterface::STATUS_BAD_REQUEST, + $request + ); + } + + $request = $request->withParsedBody($decodedBody); return $handler->handle($request); } diff --git a/tests/FreeElephants/JsonApiToolkit/AbstractHttpTestCase.php b/tests/FreeElephants/JsonApiToolkit/AbstractHttpTestCase.php index 60fec82..b7e8fc6 100644 --- a/tests/FreeElephants/JsonApiToolkit/AbstractHttpTestCase.php +++ b/tests/FreeElephants/JsonApiToolkit/AbstractHttpTestCase.php @@ -2,7 +2,10 @@ namespace FreeElephants\JsonApiToolkit; +use FreeElephants\JsonApiToolkit\Psr\ErrorFactory; +use FreeElephants\JsonApiToolkit\Psr\JsonApiResponseFactory; use Helmich\Psr7Assert\Psr7Assertions; +use Neomerx\JsonApi\Contracts\Encoder\EncoderInterface; use Nyholm\Psr7\Response; use Nyholm\Psr7\ServerRequest; use Psr\Http\Message\ResponseFactoryInterface; @@ -42,4 +45,10 @@ public function handle(ServerRequestInterface $request): ResponseInterface } }; } + + + protected function createJsonApiResponseFactory(): JsonApiResponseFactory + { + return new JsonApiResponseFactory($this->createMock(EncoderInterface::class), $this, $this->createMock(ErrorFactory::class)); + } } diff --git a/tests/FreeElephants/JsonApiToolkit/DTO/DocumentTest.php b/tests/FreeElephants/JsonApiToolkit/DTO/DocumentTest.php index 735ebec..105c7b8 100644 --- a/tests/FreeElephants/JsonApiToolkit/DTO/DocumentTest.php +++ b/tests/FreeElephants/JsonApiToolkit/DTO/DocumentTest.php @@ -28,6 +28,7 @@ public function testFromRequest() $this->assertInstanceOf(FooResource::class, $fooDTO->data); $this->assertInstanceOf(FooAttributes::class, $fooDTO->data->attributes); + $this->assertSame('foo', $fooDTO->data->type); $this->assertSame('bar', $fooDTO->data->attributes->foo); } } diff --git a/tests/FreeElephants/JsonApiToolkit/Middleware/Auth/AuthorizationTest.php b/tests/FreeElephants/JsonApiToolkit/Middleware/Auth/AuthorizationTest.php index 0a13cf9..bb4dd89 100644 --- a/tests/FreeElephants/JsonApiToolkit/Middleware/Auth/AuthorizationTest.php +++ b/tests/FreeElephants/JsonApiToolkit/Middleware/Auth/AuthorizationTest.php @@ -3,9 +3,6 @@ namespace FreeElephants\JsonApiToolkit\Middleware\Auth; use FreeElephants\JsonApiToolkit\AbstractHttpTestCase; -use FreeElephants\JsonApiToolkit\Psr\ErrorFactory; -use FreeElephants\JsonApiToolkit\Psr\JsonApiResponseFactory; -use Neomerx\JsonApi\Contracts\Encoder\EncoderInterface; use Psr\Http\Message\ServerRequestInterface; class AuthorizationTest extends AbstractHttpTestCase @@ -62,9 +59,4 @@ private function createPolicyMock(int $result = PolicyInterface::RESULT_ALLOW) return $policy; } - - private function createJsonApiResponseFactory(): JsonApiResponseFactory - { - return new JsonApiResponseFactory($this->createMock(EncoderInterface::class), $this, $this->createMock(ErrorFactory::class)); - } } diff --git a/tests/FreeElephants/JsonApiToolkit/Middleware/BodyParserMiddlewareTest.php b/tests/FreeElephants/JsonApiToolkit/Middleware/BodyParserMiddlewareTest.php deleted file mode 100644 index 1ddf4b8..0000000 --- a/tests/FreeElephants/JsonApiToolkit/Middleware/BodyParserMiddlewareTest.php +++ /dev/null @@ -1,36 +0,0 @@ -createServerRequest('POST', '/foo'); - $request->getBody()->write(<<createRequestHandlerWithAssertions(function (ServerRequestInterface $request) { - $this->assertSame([ - 'data' => [ - 'id' => 'foo', - 'type' => 'bar', - ], - ], $request->getParsedBody()); - - return $this->createResponse(); - }); - - $bodyParser = new BodyParser(); - $bodyParser->process($request, $handler); - } -} diff --git a/tests/FreeElephants/JsonApiToolkit/Middleware/BodyParserTest.php b/tests/FreeElephants/JsonApiToolkit/Middleware/BodyParserTest.php index 1f00684..cb30989 100644 --- a/tests/FreeElephants/JsonApiToolkit/Middleware/BodyParserTest.php +++ b/tests/FreeElephants/JsonApiToolkit/Middleware/BodyParserTest.php @@ -2,15 +2,18 @@ namespace FreeElephants\JsonApiToolkit\Middleware; +use Fig\Http\Message\StatusCodeInterface; use FreeElephants\JsonApiToolkit\AbstractHttpTestCase; use Psr\Http\Message\ServerRequestInterface; class BodyParserTest extends AbstractHttpTestCase { + public function testProcess() { $request = $this->createServerRequest('POST', '/foo'); - $request->getBody()->write(<<getBody()->write( + <<createRequestHandlerWithAssertions(function (ServerRequestInterface $request) { - $this->assertSame([ - 'data' => [ - 'id' => 'foo', - 'type' => 'bar', - ], - ], $request->getParsedBody()); + $handler = $this->createRequestHandlerWithAssertions( + function (ServerRequestInterface $request) { + $this->assertSame( + [ + 'data' => [ + 'id' => 'foo', + 'type' => 'bar', + ], + ], + $request->getParsedBody() + ); + + return $this->createResponse(); + } + ); + $bodyParser = new BodyParser($this->createJsonApiResponseFactory()); + $response = $bodyParser->process($request, $handler); + + $this->assertResponseHasStatus($response, StatusCodeInterface::STATUS_OK); + } + + public function testInvalidBody() + { + $request = $this->createServerRequest('POST', '/foo'); + $request->getBody()->write( + <<createRequestHandlerWithAssertions(function () { return $this->createResponse(); }); - $bodyParser = new BodyParser(); - $bodyParser->process($request, $handler); + $bodyParser = new BodyParser($this->createJsonApiResponseFactory()); + $response = $bodyParser->process($request, $handler); + + $this->assertResponseHasStatus($response, StatusCodeInterface::STATUS_BAD_REQUEST); } + }