ContentTypeHeaderMatcher.php 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. <?php
  2. namespace Drupal\Core\Routing;
  3. use Symfony\Component\HttpFoundation\Request;
  4. use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
  5. use Symfony\Component\Routing\RouteCollection;
  6. /**
  7. * Filters routes based on the HTTP Content-type header.
  8. */
  9. class ContentTypeHeaderMatcher implements FilterInterface {
  10. /**
  11. * {@inheritdoc}
  12. */
  13. public function filter(RouteCollection $collection, Request $request) {
  14. // The Content-type header does not make sense on GET or DELETE requests,
  15. // because they do not carry any content. Nothing to filter in this case.
  16. // Same for all other safe methods.
  17. if ($request->isMethodSafe(FALSE) || $request->isMethod('DELETE')) {
  18. return $collection;
  19. }
  20. $format = $request->getContentType();
  21. foreach ($collection as $name => $route) {
  22. $supported_formats = array_filter(explode('|', $route->getRequirement('_content_type_format')));
  23. if (empty($supported_formats)) {
  24. // No restriction on the route, so we move the route to the end of the
  25. // collection by re-adding it. That way generic routes sink down in the
  26. // list and exact matching routes stay on top.
  27. $collection->add($name, $route);
  28. }
  29. elseif (!in_array($format, $supported_formats)) {
  30. $collection->remove($name);
  31. }
  32. }
  33. if (count($collection)) {
  34. return $collection;
  35. }
  36. // We do not throw a
  37. // \Symfony\Component\Routing\Exception\ResourceNotFoundException here
  38. // because we don't want to return a 404 status code, but rather a 415.
  39. if (!$request->headers->get('Content-Type', FALSE)) {
  40. throw new UnsupportedMediaTypeHttpException('No "Content-Type" request header specified');
  41. }
  42. else {
  43. throw new UnsupportedMediaTypeHttpException('No route found that matches "Content-Type: ' . $request->headers->get('Content-Type') . '"');
  44. }
  45. }
  46. }