AcceptHeaderMatcher.php

Same filename in other branches
  1. 8.9.x core/modules/system/tests/modules/accept_header_routing_test/src/Routing/AcceptHeaderMatcher.php
  2. 10 core/modules/system/tests/modules/accept_header_routing_test/src/Routing/AcceptHeaderMatcher.php
  3. 11.x core/modules/system/tests/modules/accept_header_routing_test/src/Routing/AcceptHeaderMatcher.php

Namespace

Drupal\accept_header_routing_test\Routing

File

core/modules/system/tests/modules/accept_header_routing_test/src/Routing/AcceptHeaderMatcher.php

View source
<?php

namespace Drupal\accept_header_routing_test\Routing;

use Drupal\Core\Routing\FilterInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
use Symfony\Component\Routing\RouteCollection;

/**
 * Filters routes based on the media type specified in the HTTP Accept headers.
 */
class AcceptHeaderMatcher implements FilterInterface {
    
    /**
     * {@inheritdoc}
     */
    public function filter(RouteCollection $collection, Request $request) {
        // Generates a list of Symfony formats matching the acceptable MIME types.
        // @todo replace by proper content negotiation library.
        $acceptable_mime_types = $request->getAcceptableContentTypes();
        $acceptable_formats = array_filter(array_map([
            $request,
            'getFormat',
        ], $acceptable_mime_types));
        $primary_format = $request->getRequestFormat();
        foreach ($collection as $name => $route) {
            // _format could be a |-delimited list of supported formats.
            $supported_formats = array_filter(explode('|', $route->getRequirement('_format') ?? ''));
            if (empty($supported_formats)) {
                // No format restriction on the route, so it always matches. Move it to
                // the end of the collection by re-adding it.
                $collection->add($name, $route);
            }
            elseif (in_array($primary_format, $supported_formats)) {
                // Perfect match, which will get a higher priority by leaving the route
                // on top of the list.
            }
            elseif (in_array('*/*', $acceptable_mime_types) || array_intersect($acceptable_formats, $supported_formats)) {
                // Move it to the end of the list.
                $collection->add($name, $route);
            }
            else {
                // Remove the route if it does not match at all.
                $collection->remove($name);
            }
        }
        if (count($collection)) {
            return $collection;
        }
        // We do not throw a
        // \Symfony\Component\Routing\Exception\ResourceNotFoundException here
        // because we don't want to return a 404 status code, but rather a 406.
        throw new NotAcceptableHttpException('No route found for the specified formats ' . implode(' ', $acceptable_mime_types));
    }

}

Classes

Title Deprecated Summary
AcceptHeaderMatcher Filters routes based on the media type specified in the HTTP Accept headers.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.