core/core.services.yml | 4 ++ .../EventSubscriber/ExceptionJsonSubscriber.php | 11 +++++ core/lib/Drupal/Core/Routing/MethodFilter.php | 55 ++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/core/core.services.yml b/core/core.services.yml index bbc9e8e..60184b2 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -885,6 +885,10 @@ services: class: Drupal\Core\Routing\RequestFormatRouteFilter tags: - { name: route_filter } + method_filter: + class: Drupal\Core\Routing\MethodFilter + tags: + - { name: route_filter } content_type_header_matcher: class: Drupal\Core\Routing\ContentTypeHeaderMatcher tags: diff --git a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php index c06adee..399cdb9 100644 --- a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php @@ -76,4 +76,15 @@ public function on406(GetResponseForExceptionEvent $event) { $event->setResponse($response); } + /** + * Handles a 415 error for JSON. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event + * The event to process. + */ + public function on415(GetResponseForExceptionEvent $event) { + $response = new JsonResponse(['message' => $event->getException()->getMessage()], Response::HTTP_UNSUPPORTED_MEDIA_TYPE); + $event->setResponse($response); + } + } diff --git a/core/lib/Drupal/Core/Routing/MethodFilter.php b/core/lib/Drupal/Core/Routing/MethodFilter.php new file mode 100644 index 0000000..80812d4 --- /dev/null +++ b/core/lib/Drupal/Core/Routing/MethodFilter.php @@ -0,0 +1,55 @@ +getMethod(); + + $all_supported_methods = []; + + foreach ($collection as $name => $route) { + $supported_methods = $route->getMethods(); + + // A route not restricted to specific methods allows any method. If this + // is the case, we'll also have at least one route left in the collection, + // hence we don't need to calculate the set of all supported methods. + if (empty($supported_methods)) { + continue; + } + elseif (!in_array($method, $supported_methods)) { + $all_supported_methods = array_merge($supported_methods, $all_supported_methods); + $collection->remove($name); + } + } + if (count($collection)) { + return $collection; + } + throw new MethodNotAllowedException(array_unique($all_supported_methods)); + } + + /** + * {@inheritdoc} + */ + public function applies(Route $route) { + return TRUE; + } + +}