diff --git a/features/main/crud.feature b/features/main/crud.feature index 102e428a52c..96b7e63cc65 100644 --- a/features/main/crud.feature +++ b/features/main/crud.feature @@ -395,6 +395,41 @@ Feature: Create-Retrieve-Update-Delete } """ + Scenario: Update a resource with empty body + When I add "Content-Type" header equal to "application/ld+json" + And I send a "PUT" request to "/dummies/1" + Then the response status code should be 200 + And the response should be in JSON + And the header "Content-Type" should be equal to "application/ld+json; charset=utf-8" + And the JSON should be equal to: + """ + { + "@context": "/contexts/Dummy", + "@id": "/dummies/1", + "@type": "Dummy", + "description": null, + "dummy": null, + "dummyBoolean": null, + "dummyDate": "2015-03-01T10:00:00+00:00", + "dummyFloat": null, + "dummyPrice": null, + "relatedDummy": null, + "relatedDummies": [], + "jsonData": [ + { + "key": "value1" + }, + { + "key": "value2" + } + ], + "name_converted": null, + "id": 1, + "name": "A nice dummy", + "alias": null + } + """ + @dropSchema Scenario: Delete a resource When I send a "DELETE" request to "/dummies/1" diff --git a/src/EventListener/DeserializeListener.php b/src/EventListener/DeserializeListener.php index 33b52d858ca..563a27b5540 100644 --- a/src/EventListener/DeserializeListener.php +++ b/src/EventListener/DeserializeListener.php @@ -51,6 +51,7 @@ public function onKernelRequest(GetResponseEvent $event) || $request->isMethod(Request::METHOD_DELETE) || !($attributes = RequestAttributesExtractor::extractAttributes($request)) || !$attributes['receive'] + || ('' === ($requestContent = $request->getContent()) && $request->isMethod(Request::METHOD_PUT)) ) { return; } @@ -66,7 +67,7 @@ public function onKernelRequest(GetResponseEvent $event) $request->attributes->set( 'data', $this->serializer->deserialize( - $request->getContent(), $attributes['resource_class'], $format, $context + $requestContent, $attributes['resource_class'], $format, $context ) ); } diff --git a/tests/EventListener/DeserializeListenerTest.php b/tests/EventListener/DeserializeListenerTest.php index 41316500580..1885c795494 100644 --- a/tests/EventListener/DeserializeListenerTest.php +++ b/tests/EventListener/DeserializeListenerTest.php @@ -45,6 +45,25 @@ public function testDoNotCallWhenRequestMethodIsSafe() $listener->onKernelRequest($eventProphecy->reveal()); } + public function testDoNotCallWhenPutAndEmptyRequestContent() + { + $eventProphecy = $this->prophesize(GetResponseEvent::class); + + $request = new Request([], [], ['data' => new \stdClass(), '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'put'], [], [], [], ''); + $request->setMethod(Request::METHOD_PUT); + $request->headers->set('Content-Type', 'application/json'); + $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + + $serializerProphecy = $this->prophesize(SerializerInterface::class); + $serializerProphecy->deserialize()->shouldNotBeCalled(); + + $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); + $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), false, Argument::type('array'))->shouldNotBeCalled(); + + $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), self::FORMATS); + $listener->onKernelRequest($eventProphecy->reveal()); + } + public function testDoNotCallWhenRequestNotManaged() { $eventProphecy = $this->prophesize(GetResponseEvent::class);