diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php index d96df4d..b372a62 100644 --- a/core/modules/rest/src/RequestHandler.php +++ b/core/modules/rest/src/RequestHandler.php @@ -105,29 +105,27 @@ public function handle(RouteMatchInterface $route_match, Request $request) { // Serialize the outgoing data for the response, if available. if ($response instanceof ResourceResponse) { $data = $response->getResponseData(); - if (!is_scalar($data)) { - // Serialization can invoke rendering (e.g., generating URLs), but the - // serialization API does not provide a mechanism to collect the - // bubbleable metadata associated with that (e.g., language and other - // contexts), so instead, allow those to "leak" and collect them here in - // a render context. - // @todo Add test coverage for language negotiation contexts in - // https://www.drupal.org/node/2135829. - $context = new RenderContext(); - $output = $this->container->get('renderer') - ->executeInRenderContext($context, function () use ($serializer, $data, $format) { - return $serializer->serialize($data, $format); - }); - $response->setContent($output); - if (!$context->isEmpty()) { - $response->addCacheableDependency($context->pop()); - } - - $response->headers->set('Content-Type', $request->getMimeType($format)); - // Add rest settings config's cache tags. - $response->addCacheableDependency($this->container->get('config.factory') - ->get('rest.settings')); + // Serialization can invoke rendering (e.g., generating URLs), but the + // serialization API does not provide a mechanism to collect the + // bubbleable metadata associated with that (e.g., language and other + // contexts), so instead, allow those to "leak" and collect them here in + // a render context. + // @todo Add test coverage for language negotiation contexts in + // https://www.drupal.org/node/2135829. + $context = new RenderContext(); + $output = $this->container->get('renderer') + ->executeInRenderContext($context, function () use ($serializer, $data, $format) { + return $serializer->serialize($data, $format); + }); + $response->setContent($output); + if (!$context->isEmpty()) { + $response->addCacheableDependency($context->pop()); } + + $response->headers->set('Content-Type', $request->getMimeType($format)); + // Add rest settings config's cache tags. + $response->addCacheableDependency($this->container->get('config.factory') + ->get('rest.settings')); } return $response; } diff --git a/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php b/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php index c0352cf..969804f 100644 --- a/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php +++ b/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php @@ -37,9 +37,6 @@ class RequestHandlerTest extends KernelTestBase { */ public function setUp() { parent::setUp(); -// /** @var \Drupal\rest\Plugin\Type\ResourcePluginManager $plugin_manager */ -// $plugin_manager = $this->container->get('plugin.manager.rest'); - $this->requestHandler = new RequestHandler(); $this->requestHandler->setContainer($this->container); } @@ -50,22 +47,21 @@ public function setUp() { * @covers ::handle */ public function testBaseHandler() { - $request = new Request(); - $route_match = new RouteMatch('test', new Route('/rest/test', ['_plugin' => 'restplugin'])); + $route_match = new RouteMatch('test', new Route('/rest/test', ['_plugin' => 'restplugin', '_format' => 'json'])); $resource = $this->prophesize(StubRequestHandlerResourcePlugin::class); - // Assert get plugin method is called. $resource->get(NULL, $request) ->shouldBeCalled(); - // Setup stubbed out plugin manager that will return our plugin. + // Setup stub plugin manager that will return our plugin. $stub = $this->prophesize(ResourcePluginManager::class); $stub->getInstance(['id' => 'restplugin']) ->willReturn($resource->reveal()); $this->container->set('plugin.manager.rest', $stub->reveal()); - // Response returns null this time. + // Response returns NULL this time because response from plugin is not + // a ResourceResponse so it is passed through directory. $response = $this->requestHandler->handle($route_match, $request); $this->assertEquals(NULL, $response); @@ -89,51 +85,44 @@ public function testBaseHandler() { /** * Test that given structured data, the request handler will serialize it. * + * @dataProvider providerTestSerialization * @covers ::handle */ - public function testSerialization() { + public function testSerialization($data) { $request = new Request(); - $route_match = new RouteMatch('test', new Route('/rest/test', ['_plugin' => 'restplugin'])); + $route_match = new RouteMatch('test', new Route('/rest/test', ['_plugin' => 'restplugin', '_format' => 'json'])); $resource = $this->prophesize(StubRequestHandlerResourcePlugin::class); - // Setup stubbed out plugin manager that will return our plugin. + // Setup stub plugin manager that will return our plugin. $stub = $this->prophesize(ResourcePluginManager::class); $stub->getInstance(['id' => 'restplugin']) ->willReturn($resource->reveal()); $this->container->set('plugin.manager.rest', $stub->reveal()); - $response = new ResourceResponse(['test']); + $response = new ResourceResponse($data); $resource->get(NULL, $request) ->willReturn($response); $handler_response = $this->requestHandler->handle($route_match, $request); // Content is a serialized version of the data we provided. - $this->assertEquals(json_encode(['test']), $handler_response->getContent()); + $this->assertEquals(json_encode($data), $handler_response->getContent()); } - /** - * Test that we can serialize an empty dataset. - * - * @covers ::handle - */ - public function testEmptySerialization() { - $request = new Request(); - $route_match = new RouteMatch('test', new Route('/rest/test', ['_plugin' => 'restplugin'])); - - $resource = $this->prophesize(StubRequestHandlerResourcePlugin::class); - - // Setup stubbed out plugin manager that will return our plugin. - $stub = $this->prophesize(ResourcePluginManager::class); - $stub->getInstance(['id' => 'restplugin']) - ->willReturn($resource->reveal()); - $this->container->set('plugin.manager.rest', $stub->reveal()); - - $response = new ResourceResponse([]); - $resource->get(NULL, $request) - ->willReturn($response); - $handler_response = $this->requestHandler->handle($route_match, $request); - // Content is a serialized version of the data we provided. - $this->assertEquals(json_encode([]), $handler_response->getContent()); + public function providerTestSerialization() { + return [ + [NULL], + [''], + ['string'], + ['Complex \ string $%^&@ with unicode ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ'], + [[]], + [['test']], + [['test' => 'foobar']], + [TRUE], + [FALSE], + // TODO Not supported. https://www.drupal.org/node/2427811 + // [new \stdClass()], + // [(object) ['test' => 'foobar']], + ]; } }