From 04f1dcfad414c24eaba8a949c32c3247b9282368 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Thu, 4 May 2023 11:28:18 +0100
Subject: [PATCH] Issue #3093973 by robindh, Diego_Mow, smustgrave, Grayle:
 Allow DELETE requests to return a response body

(cherry picked from commit a5b62885f581de61effd1de1175208f668c5308b)
---
 .../ResourceResponseSubscriber.php            |  5 ++---
 .../rest/src/Routing/ResourceRoutes.php       |  2 +-
 .../ResourceResponseSubscriberTest.php        | 22 +++++++++----------
 3 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/core/modules/rest/src/EventSubscriber/ResourceResponseSubscriber.php b/core/modules/rest/src/EventSubscriber/ResourceResponseSubscriber.php
index 02330d2c636a..d01fcbfa30e8 100644
--- a/core/modules/rest/src/EventSubscriber/ResourceResponseSubscriber.php
+++ b/core/modules/rest/src/EventSubscriber/ResourceResponseSubscriber.php
@@ -122,7 +122,7 @@ public function getResponseFormat(RouteMatchInterface $route_match, Request $req
       return $acceptable_formats[0];
     }
 
-    // Sometimes, there are no acceptable formats, e.g. DELETE routes.
+    // Sometimes, there are no acceptable formats.
     return NULL;
   }
 
@@ -141,8 +141,7 @@ public function getResponseFormat(RouteMatchInterface $route_match, Request $req
    * @param \Symfony\Component\Serializer\SerializerInterface $serializer
    *   The serializer to use.
    * @param string|null $format
-   *   The response format, or NULL in case the response does not need a format,
-   *   for example for the response to a DELETE request.
+   *   The response format, or NULL in case the response does not need a format.
    *
    * @todo Add test coverage for language negotiation contexts in
    *   https://www.drupal.org/node/2135829.
diff --git a/core/modules/rest/src/Routing/ResourceRoutes.php b/core/modules/rest/src/Routing/ResourceRoutes.php
index f4628130f81c..a3cfe746057d 100644
--- a/core/modules/rest/src/Routing/ResourceRoutes.php
+++ b/core/modules/rest/src/Routing/ResourceRoutes.php
@@ -116,7 +116,7 @@ protected function getRoutesForResourceConfig(RestResourceConfigInterface $rest_
         // - set the allowed request body content types/formats for methods that
         //   allow request bodies to be sent (unless hardcoded by the plugin)
         // - set the allowed authentication providers
-        if (in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'PATCH'], TRUE) && !$route->hasRequirement('_format')) {
+        if (in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'], TRUE) && !$route->hasRequirement('_format')) {
           $route->addRequirements(['_format' => implode('|', $rest_resource_config->getFormats($method))]);
         }
         if (in_array($method, ['POST', 'PATCH', 'PUT'], TRUE) && !$route->hasRequirement('_content_type_format')) {
diff --git a/core/modules/rest/tests/src/Unit/EventSubscriber/ResourceResponseSubscriberTest.php b/core/modules/rest/tests/src/Unit/EventSubscriber/ResourceResponseSubscriberTest.php
index 44f5d55dc4a4..3efc3f021ab8 100644
--- a/core/modules/rest/tests/src/Unit/EventSubscriber/ResourceResponseSubscriberTest.php
+++ b/core/modules/rest/tests/src/Unit/EventSubscriber/ResourceResponseSubscriberTest.php
@@ -136,7 +136,7 @@ public function testOnResponseWithCacheableResponse($methods, array $supported_r
       $route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => $this->randomMachineName()], $route_requirements));
 
       // The RequestHandler must return a ResourceResponseInterface object.
-      $handler_response = new ResourceResponse($method !== 'DELETE' ? ['REST' => 'Drupal'] : NULL);
+      $handler_response = new ResourceResponse(['REST' => 'Drupal']);
       $this->assertInstanceOf(ResourceResponseInterface::class, $handler_response);
       $this->assertInstanceOf(CacheableResponseInterface::class, $handler_response);
 
@@ -186,7 +186,7 @@ public function testOnResponseWithUncacheableResponse($methods, array $supported
       $route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => $this->randomMachineName()], $route_requirements));
 
       // The RequestHandler must return a ResourceResponseInterface object.
-      $handler_response = new ModifiedResourceResponse($method !== 'DELETE' ? ['REST' => 'Drupal'] : NULL);
+      $handler_response = new ModifiedResourceResponse(['REST' => 'Drupal']);
       $this->assertInstanceOf(ResourceResponseInterface::class, $handler_response);
       $this->assertNotInstanceOf(CacheableResponseInterface::class, $handler_response);
 
@@ -344,7 +344,7 @@ public function providerTestResponseFormat() {
     ];
 
     $unsafe_method_bodyless_test_cases = [
-      'unsafe methods without response bodies (DELETE): client requested no format, response should have no format' => [
+      'unsafe methods without request bodies (DELETE): client requested no format, response should have the first acceptable format' => [
         ['DELETE'],
         ['xml', 'json'],
         ['xml', 'json'],
@@ -352,10 +352,10 @@ public function providerTestResponseFormat() {
         ['Content-Type' => 'application/json'],
         NULL,
         'xml',
-        NULL,
-        '',
+        'text/xml',
+        $xml_encoded,
       ],
-      'unsafe methods without response bodies (DELETE): client requested format (XML), response should have no format' => [
+      'unsafe methods without request bodies (DELETE): client requested format (XML), response should have xml format' => [
         ['DELETE'],
         ['xml', 'json'],
         ['xml', 'json'],
@@ -363,10 +363,10 @@ public function providerTestResponseFormat() {
         ['Content-Type' => 'application/json'],
         NULL,
         'xml',
-        NULL,
-        '',
+        'text/xml',
+        $xml_encoded,
       ],
-      'unsafe methods without response bodies (DELETE): client requested format (JSON), response should have no format' => [
+      'unsafe methods without request bodies (DELETE): client requested format (JSON), response should have json format' => [
         ['DELETE'],
         ['xml', 'json'],
         ['xml', 'json'],
@@ -374,8 +374,8 @@ public function providerTestResponseFormat() {
         ['Content-Type' => 'application/json'],
         NULL,
         'json',
-        NULL,
-        '',
+        'application/json',
+        $json_encoded,
       ],
     ];
 
-- 
GitLab