Issue #2445723 by dawehner, neclimdul: Use the $request format instead of the ContentNegotation
parent
566bc8bdb9
commit
13e0794edc
|
@ -486,6 +486,18 @@ services:
|
|||
http_kernel.basic:
|
||||
class: Symfony\Component\HttpKernel\HttpKernel
|
||||
arguments: ['@event_dispatcher', '@controller_resolver', '@request_stack']
|
||||
http_negotiation.format_negotiator:
|
||||
class: Drupal\Core\ContentNegotiation
|
||||
private: true
|
||||
http_middleware.negotiation:
|
||||
class: Drupal\Core\StackMiddleware\NegotiationMiddleware
|
||||
arguments: ['@http_negotiation.format_negotiator']
|
||||
calls:
|
||||
- [registerFormat, ['drupal_ajax', ['application/vnd.drupal-ajax']]]
|
||||
- [registerFormat, ['drupal_dialog', ['application/vnd.drupal-dialog']]]
|
||||
- [registerFormat, ['drupal_modal', ['application/vnd.drupal-modal']]]
|
||||
tags:
|
||||
- { name: http_middleware, priority: 400 }
|
||||
http_middleware.reverse_proxy:
|
||||
class: Drupal\Core\StackMiddleware\ReverseProxyMiddleware
|
||||
arguments: ['@settings']
|
||||
|
@ -493,7 +505,7 @@ services:
|
|||
- { name: http_middleware, priority: 300 }
|
||||
http_middleware.page_cache:
|
||||
class: Drupal\Core\StackMiddleware\PageCache
|
||||
arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy', '@content_negotiation']
|
||||
arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy']
|
||||
tags:
|
||||
- { name: http_middleware, priority: 200 }
|
||||
http_middleware.kernel_pre_handle:
|
||||
|
@ -571,7 +583,7 @@ services:
|
|||
- { name: backend_overridable }
|
||||
router.route_preloader:
|
||||
class: Drupal\Core\Routing\RoutePreloader
|
||||
arguments: ['@router.route_provider', '@state', '@content_negotiation']
|
||||
arguments: ['@router.route_provider', '@state']
|
||||
tags:
|
||||
- { name: 'event_subscriber' }
|
||||
router.matcher.final_matcher:
|
||||
|
@ -682,7 +694,6 @@ services:
|
|||
arguments: [16]
|
||||
accept_header_matcher:
|
||||
class: Drupal\Core\Routing\AcceptHeaderMatcher
|
||||
arguments: ['@content_negotiation']
|
||||
tags:
|
||||
- { name: route_filter }
|
||||
content_type_header_matcher:
|
||||
|
@ -749,7 +760,6 @@ services:
|
|||
- { name: route_enhancer, priority: 20 }
|
||||
route_content_controller_subscriber:
|
||||
class: Drupal\Core\EventSubscriber\ContentControllerSubscriber
|
||||
arguments: ['@content_negotiation']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
route_special_attributes_subscriber:
|
||||
|
@ -799,13 +809,11 @@ services:
|
|||
tags:
|
||||
- { name: event_subscriber }
|
||||
arguments: ['@router', '@router.request_context', NULL, '@request_stack']
|
||||
content_negotiation:
|
||||
class: Drupal\Core\ContentNegotiation
|
||||
view_subscriber:
|
||||
class: Drupal\Core\EventSubscriber\ViewSubscriber
|
||||
arguments: ['@title_resolver']
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
arguments: ['@content_negotiation', '@title_resolver']
|
||||
bare_html_page_renderer:
|
||||
class: Drupal\Core\Render\BareHtmlPageRenderer
|
||||
arguments: ['@renderer']
|
||||
|
@ -1003,10 +1011,6 @@ services:
|
|||
- { name: event_subscriber }
|
||||
calls:
|
||||
- [setContainer, ['@service_container']]
|
||||
ajax.subscriber:
|
||||
class: Drupal\Core\Ajax\AjaxSubscriber
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
image.toolkit.manager:
|
||||
class: Drupal\Core\ImageToolkit\ImageToolkitManager
|
||||
arguments: ['@config.factory']
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Ajax\AjaxSubscriber.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Ajax;
|
||||
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Subscribes to the kernel request event to add the Ajax media type.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
||||
* The event to process.
|
||||
*/
|
||||
class AjaxSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* Registers Ajax formats with the Request class.
|
||||
*/
|
||||
public function onKernelRequest(GetResponseEvent $event) {
|
||||
$request = $event->getRequest();
|
||||
$request->setFormat('drupal_ajax', 'application/vnd.drupal-ajax');
|
||||
$request->setFormat('drupal_dialog', 'application/vnd.drupal-dialog');
|
||||
$request->setFormat('drupal_modal', 'application/vnd.drupal-modal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the methods in this class that should be listeners.
|
||||
*
|
||||
* @return array
|
||||
* An array of event listener definitions.
|
||||
*/
|
||||
static function getSubscribedEvents(){
|
||||
$events[KernelEvents::REQUEST][] = array('onKernelRequest', 50);
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace Drupal\Core\EventSubscriber;
|
||||
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
@ -20,39 +19,6 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
|||
*/
|
||||
class ContentControllerSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* Content negotiation library.
|
||||
*
|
||||
* @var \Drupal\Core\ContentNegotiation
|
||||
*/
|
||||
protected $negotiation;
|
||||
|
||||
/**
|
||||
* Constructs a new ContentControllerSubscriber object.
|
||||
*
|
||||
* @param \Drupal\Core\ContentNegotiation $negotiation
|
||||
* The Content Negotiation service.
|
||||
*/
|
||||
public function __construct(ContentNegotiation $negotiation) {
|
||||
$this->negotiation = $negotiation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the derived request format on the request.
|
||||
*
|
||||
* @todo Remove when https://www.drupal.org/node/2331919 lands.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
||||
* The event to process.
|
||||
*/
|
||||
public function onRequestDeriveFormat(GetResponseEvent $event) {
|
||||
$request = $event->getRequest();
|
||||
|
||||
if (!$request->attributes->get('_format')) {
|
||||
$request->setRequestFormat($this->negotiation->getContentType($request));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the _controller on a request when a _form is defined.
|
||||
*
|
||||
|
@ -74,7 +40,6 @@ class ContentControllerSubscriber implements EventSubscriberInterface {
|
|||
* An array of event listener definitions.
|
||||
*/
|
||||
static function getSubscribedEvents() {
|
||||
$events[KernelEvents::REQUEST][] = array('onRequestDeriveFormat', 31);
|
||||
$events[KernelEvents::REQUEST][] = array('onRequestDeriveFormWrapper', 29);
|
||||
|
||||
return $events;
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace Drupal\Core\EventSubscriber;
|
|||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\String;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Drupal\Core\Render\BareHtmlPageRendererInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\Utility\Error;
|
||||
|
@ -206,8 +205,7 @@ class DefaultExceptionSubscriber implements EventSubscriberInterface {
|
|||
// to this code. We therefore use this style for now on the expectation
|
||||
// that it will get replaced with better code later. This approach makes
|
||||
// that change easier when we get to it.
|
||||
$conneg = new ContentNegotiation();
|
||||
$format = $conneg->getContentType($request);
|
||||
$format = \Drupal::service('http_negotiation.format_negotiator')->getContentType($request);
|
||||
|
||||
// These are all JSON errors for our purposes. Any special handling for
|
||||
// them can/should happen in earlier listeners if desired.
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace Drupal\Core\EventSubscriber;
|
||||
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
|
@ -91,16 +90,7 @@ abstract class HttpExceptionSubscriberBase implements EventSubscriberInterface {
|
|||
|
||||
$handled_formats = $this->getHandledFormats();
|
||||
|
||||
// @todo Injecting this service would force all implementing classes to also
|
||||
// handle its injection. However, we are trying to switch to a more robust
|
||||
// content negotiation library in https://www.drupal.org/node/1505080 that
|
||||
// will make $request->getRequestFormat() reliable as a better alternative
|
||||
// to this code. We therefore use this style for now on the expectation
|
||||
// that it will get replaced with better code later. That change will NOT
|
||||
// be an API change for any implementing classes. (Whereas if we injected
|
||||
// this class it would be an API change. That's why we're not doing it.)
|
||||
$conneg = new ContentNegotiation();
|
||||
$format = $conneg->getContentType($event->getRequest());
|
||||
$format = $event->getRequest()->getRequestFormat();
|
||||
|
||||
if ($exception instanceof HttpExceptionInterface && (empty($handled_formats) || in_array($format, $handled_formats))) {
|
||||
$method = 'on' . $exception->getStatusCode();
|
||||
|
|
|
@ -16,8 +16,6 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
|
|||
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
|
||||
/**
|
||||
* Main subscriber for VIEW HTTP responses.
|
||||
*
|
||||
|
@ -27,13 +25,6 @@ use Drupal\Core\ContentNegotiation;
|
|||
*/
|
||||
class ViewSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The content negotiation.
|
||||
*
|
||||
* @var \Drupal\Core\ContentNegotiation
|
||||
*/
|
||||
protected $negotiation;
|
||||
|
||||
/**
|
||||
* The title resolver.
|
||||
*
|
||||
|
@ -41,17 +32,13 @@ class ViewSubscriber implements EventSubscriberInterface {
|
|||
*/
|
||||
protected $titleResolver;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new ViewSubscriber.
|
||||
*
|
||||
* @param \Drupal\Core\ContentNegotiation $negotiation
|
||||
* The content negotiation.
|
||||
* @param \Drupal\Core\Controller\TitleResolverInterface $title_resolver
|
||||
* The title resolver.
|
||||
*/
|
||||
public function __construct(ContentNegotiation $negotiation, TitleResolverInterface $title_resolver) {
|
||||
$this->negotiation = $negotiation;
|
||||
public function __construct(TitleResolverInterface $title_resolver) {
|
||||
$this->titleResolver = $title_resolver;
|
||||
}
|
||||
|
||||
|
@ -64,14 +51,14 @@ class ViewSubscriber implements EventSubscriberInterface {
|
|||
* from an JSON-type response is a JSON string, so just wrap it into a
|
||||
* Response object.
|
||||
*
|
||||
* @param Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event
|
||||
* The Event to process.
|
||||
*/
|
||||
public function onView(GetResponseForControllerResultEvent $event) {
|
||||
$request = $event->getRequest();
|
||||
|
||||
if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) {
|
||||
$method = 'on' . $this->negotiation->getContentType($request);
|
||||
$method = 'on' . $request->getRequestFormat();
|
||||
|
||||
if (method_exists($this, $method)) {
|
||||
$event->setResponse($this->$method($event));
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Drupal\Core\Routing;
|
||||
|
||||
use Drupal\Component\Utility\String;
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
@ -19,23 +18,6 @@ use Symfony\Component\Routing\RouteCollection;
|
|||
*/
|
||||
class AcceptHeaderMatcher implements RouteFilterInterface {
|
||||
|
||||
/**
|
||||
* The content negotiation library.
|
||||
*
|
||||
* @var \Drupal\Core\ContentNegotiation
|
||||
*/
|
||||
protected $contentNegotiation;
|
||||
|
||||
/**
|
||||
* Constructs a new AcceptHeaderMatcher.
|
||||
*
|
||||
* @param \Drupal\Core\ContentNegotiation $content_negotiation
|
||||
* The content negotiation library.
|
||||
*/
|
||||
public function __construct(ContentNegotiation $content_negotiation) {
|
||||
$this->contentNegotiation = $content_negotiation;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -44,7 +26,7 @@ class AcceptHeaderMatcher implements RouteFilterInterface {
|
|||
// @todo replace by proper content negotiation library.
|
||||
$acceptable_mime_types = $request->getAcceptableContentTypes();
|
||||
$acceptable_formats = array_filter(array_map(array($request, 'getFormat'), $acceptable_mime_types));
|
||||
$primary_format = $this->contentNegotiation->getContentType($request);
|
||||
$primary_format = $request->getRequestFormat();
|
||||
|
||||
foreach ($collection as $name => $route) {
|
||||
// _format could be a |-delimited list of supported formats.
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace Drupal\Core\Routing;
|
||||
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
@ -37,13 +36,6 @@ class RoutePreloader implements EventSubscriberInterface {
|
|||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The content negotiation.
|
||||
*
|
||||
* @var \Drupal\Core\ContentNegotiation
|
||||
*/
|
||||
protected $negotiation;
|
||||
|
||||
/**
|
||||
* Contains the non-admin routes while rebuilding the routes.
|
||||
*
|
||||
|
@ -58,13 +50,10 @@ class RoutePreloader implements EventSubscriberInterface {
|
|||
* The route provider.
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state key value store.
|
||||
* @param \Drupal\Core\ContentNegotiation $negotiation
|
||||
* The content negotiation.
|
||||
*/
|
||||
public function __construct(RouteProviderInterface $route_provider, StateInterface $state, ContentNegotiation $negotiation) {
|
||||
public function __construct(RouteProviderInterface $route_provider, StateInterface $state) {
|
||||
$this->routeProvider = $route_provider;
|
||||
$this->state = $state;
|
||||
$this->negotiation = $negotiation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,7 +64,7 @@ class RoutePreloader implements EventSubscriberInterface {
|
|||
*/
|
||||
public function onRequest(KernelEvent $event) {
|
||||
// Just preload on normal HTML pages, as they will display menu links.
|
||||
if ($this->negotiation->getContentType($event->getRequest()) == 'html') {
|
||||
if ($event->getRequest()->getRequestFormat() == 'html') {
|
||||
$this->loadNonAdminRoutes();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\StackMiddleware\NegotationMiddleware.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\StackMiddleware;
|
||||
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Drupal\Core\ContentNegotiationInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Provides a middleware to determine the content type upon the accept header.
|
||||
*
|
||||
* @todo This is a temporary solution, remove this in https://www.drupal.org/node/2364011
|
||||
*/
|
||||
class NegotiationMiddleware implements HttpKernelInterface {
|
||||
|
||||
/**
|
||||
* The wrapped HTTP kernel.
|
||||
*
|
||||
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* The content negotiator.
|
||||
*
|
||||
* @var \Drupal\Core\ContentNegotiation
|
||||
*/
|
||||
protected $negotiator;
|
||||
|
||||
/**
|
||||
* Contains a hashmap of format as key and mimetype as value.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $formats;
|
||||
|
||||
/**
|
||||
* Constructs a new NegotiationMiddleware.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\HttpKernelInterface $app
|
||||
* The wrapper HTTP kernel
|
||||
* @param \Drupal\Core\ContentNegotiation $negotiator
|
||||
* The content negotiator.
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $app, ContentNegotiation $negotiator) {
|
||||
$this->app = $app;
|
||||
$this->negotiator = $negotiator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) {
|
||||
foreach ($this->formats as $format => $mime_type) {
|
||||
$request->setFormat($format, $mime_type);
|
||||
}
|
||||
|
||||
$request->setRequestFormat($this->negotiator->getContentType($request));
|
||||
return $this->app->handle($request, $type, $catch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a format for a given MIME type.
|
||||
*
|
||||
* @param string $format
|
||||
* The format.
|
||||
* @param string $mime_type
|
||||
* The MIME type.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function registerFormat($format, $mime_type) {
|
||||
$this->formats[$format] = $mime_type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,7 +9,6 @@ namespace Drupal\Core\StackMiddleware;
|
|||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Drupal\Core\PageCache\RequestPolicyInterface;
|
||||
use Drupal\Core\PageCache\ResponsePolicyInterface;
|
||||
use Drupal\Core\Site\Settings;
|
||||
|
@ -52,13 +51,6 @@ class PageCache implements HttpKernelInterface {
|
|||
*/
|
||||
protected $responsePolicy;
|
||||
|
||||
/**
|
||||
* The content negotiation library.
|
||||
*
|
||||
* @var \Drupal\Core\ContentNegotiation
|
||||
*/
|
||||
protected $contentNegotiation;
|
||||
|
||||
/**
|
||||
* Constructs a ReverseProxyMiddleware object.
|
||||
*
|
||||
|
@ -70,15 +62,12 @@ class PageCache implements HttpKernelInterface {
|
|||
* A policy rule determining the cacheability of a request.
|
||||
* @param \Drupal\Core\PageCache\ResponsePolicyInterface $response_policy
|
||||
* A policy rule determining the cacheability of the response.
|
||||
* @param \Drupal\Core\ContentNegotiation $content_negotiation
|
||||
* The content negotiation library.
|
||||
*/
|
||||
public function __construct(HttpKernelInterface $http_kernel, CacheBackendInterface $cache, RequestPolicyInterface $request_policy, ResponsePolicyInterface $response_policy, ContentNegotiation $content_negotiation) {
|
||||
public function __construct(HttpKernelInterface $http_kernel, CacheBackendInterface $cache, RequestPolicyInterface $request_policy, ResponsePolicyInterface $response_policy) {
|
||||
$this->httpKernel = $http_kernel;
|
||||
$this->cache = $cache;
|
||||
$this->requestPolicy = $request_policy;
|
||||
$this->responsePolicy = $response_policy;
|
||||
$this->contentNegotiation = $content_negotiation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,7 +321,7 @@ class PageCache implements HttpKernelInterface {
|
|||
protected function getCacheId(Request $request) {
|
||||
$cid_parts = array(
|
||||
$request->getUri(),
|
||||
$this->contentNegotiation->getContentType($request),
|
||||
$request->getRequestFormat(),
|
||||
);
|
||||
return implode(':', $cid_parts);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,3 @@ services:
|
|||
class: Drupal\hal\Encoder\JsonEncoder
|
||||
tags:
|
||||
- { name: encoder, priority: 10, format: hal_json }
|
||||
hal.subscriber:
|
||||
class: Drupal\hal\HalSubscriber
|
||||
tags:
|
||||
- { name: event_subscriber }
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\HalServiceProvider.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
|
||||
|
||||
/**
|
||||
* Adds hal+json as known format.
|
||||
*/
|
||||
class HalServiceProvider implements ServiceModifierInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
if ($container->has('http_middleware.negotiation')) {
|
||||
$container->getDefinition('http_middleware.negotiation')->addMethodCall('registerFormat', ['hal_json', ['application/hal+json']]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\hal\HalSubscriber.
|
||||
*/
|
||||
|
||||
namespace Drupal\hal;
|
||||
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Subscribes to the kernel request event to add HAL media types.
|
||||
*/
|
||||
class HalSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* Registers HAL formats with the Request class.
|
||||
*
|
||||
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
|
||||
* The event to process.
|
||||
*/
|
||||
public function onKernelRequest(GetResponseEvent $event) {
|
||||
$request = $event->getRequest();
|
||||
$request->setFormat('hal_json', 'application/hal+json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the methods in this class that should be listeners.
|
||||
*
|
||||
* @return array
|
||||
* An array of event listener definitions.
|
||||
*/
|
||||
static function getSubscribedEvents() {
|
||||
$events[KernelEvents::REQUEST][] = array('onKernelRequest', 40);
|
||||
return $events;
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,6 @@ namespace Drupal\rest\Plugin\views\display;
|
|||
use Drupal\Component\Utility\String;
|
||||
use Drupal\Core\State\StateInterface;
|
||||
use Drupal\Core\Routing\RouteProviderInterface;
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Drupal\views\ViewExecutable;
|
||||
use Drupal\views\Plugin\views\display\PathPluginBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
@ -72,13 +71,6 @@ class RestExport extends PathPluginBase {
|
|||
*/
|
||||
protected $mimeType;
|
||||
|
||||
/**
|
||||
* The content negotiation library.
|
||||
*
|
||||
* @var \Drupal\Core\ContentNegotiation
|
||||
*/
|
||||
protected $contentNegotiation;
|
||||
|
||||
/**
|
||||
* Constructs a Drupal\rest\Plugin\ResourceBase object.
|
||||
*
|
||||
|
@ -92,12 +84,9 @@ class RestExport extends PathPluginBase {
|
|||
* The route provider
|
||||
* @param \Drupal\Core\State\StateInterface $state
|
||||
* The state key value store.
|
||||
* @param \Drupal\Core\ContentNegotiation $content_negotiation
|
||||
* The content negotiation library.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, StateInterface $state, ContentNegotiation $content_negotiation) {
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteProviderInterface $route_provider, StateInterface $state) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition, $route_provider, $state);
|
||||
$this->contentNegotiation = $content_negotiation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,8 +98,7 @@ class RestExport extends PathPluginBase {
|
|||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('router.route_provider'),
|
||||
$container->get('state'),
|
||||
$container->get('content_negotiation')
|
||||
$container->get('state')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -120,7 +108,7 @@ class RestExport extends PathPluginBase {
|
|||
public function initDisplay(ViewExecutable $view, array &$display, array &$options = NULL) {
|
||||
parent::initDisplay($view, $display, $options);
|
||||
|
||||
$request_content_type = $this->contentNegotiation->getContentType($this->view->getRequest());
|
||||
$request_content_type = $this->view->getRequest()->getRequestFormat();
|
||||
// Only use the requested content type if it's not 'html'. If it is then
|
||||
// default to 'json' to aid debugging.
|
||||
// @todo Remove the need for this when we have better content negotiation.
|
||||
|
|
|
@ -40,16 +40,10 @@ class CollectRoutesTest extends UnitTestCase {
|
|||
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
$content_negotiation = $this->getMockBuilder('\Drupal\Core\ContentNegotiation')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$container->set('content_negotiation', $content_negotiation);
|
||||
|
||||
$this->view = $this->getMock('\Drupal\views\Entity\View', array('initHandlers'), array(
|
||||
array('id' => 'test_view'),
|
||||
'view',
|
||||
|
|
|
@ -11,6 +11,7 @@ use Drupal\Component\Datetime\DateTimePlus;
|
|||
use Drupal\Core\Routing\RequestContext;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\user\Entity\Role;
|
||||
|
||||
/**
|
||||
* Enables the page cache and tests it with various HTTP requests.
|
||||
|
@ -98,6 +99,50 @@ class PageCacheTest extends WebTestBase {
|
|||
$this->drupalGet($accept_header_cache_uri, array(), $json_accept_header);
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Json response was cached.');
|
||||
$this->assertRaw('{"content":"oh hai this is json"}', 'The correct Json response was returned.');
|
||||
|
||||
// Enable REST support for nodes and hal+json.
|
||||
\Drupal::service('module_installer')->install(['node', 'rest', 'hal']);
|
||||
$this->drupalCreateContentType(['type' => 'article']);
|
||||
$node = $this->drupalCreateNode(['type' => 'article']);
|
||||
$node_uri = 'node/' . $node->id();
|
||||
$hal_json_accept_header = ['Accept: application/hal+json'];
|
||||
/** @var \Drupal\user\RoleInterface $role */
|
||||
$role = Role::load('anonymous');
|
||||
$role->grantPermission('restful get entity:node');
|
||||
$role->save();
|
||||
|
||||
$this->drupalGet($node_uri);
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Type'), 'text/html; charset=UTF-8');
|
||||
$this->drupalGet($node_uri);
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Type'), 'text/html; charset=UTF-8');
|
||||
|
||||
// Now request a HAL page, we expect that the first request is a cache miss
|
||||
// and it serves HTML.
|
||||
$this->drupalGet($node_uri, [], $hal_json_accept_header);
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/hal+json');
|
||||
$this->drupalGet($node_uri, [], $hal_json_accept_header);
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/hal+json');
|
||||
|
||||
// Clear the page cache. After that request a HAL request, followed by an
|
||||
// ordinary HTML one.
|
||||
\Drupal::cache('render')->deleteAll();
|
||||
$this->drupalGet($node_uri, [], $hal_json_accept_header);
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/hal+json');
|
||||
$this->drupalGet($node_uri, [], $hal_json_accept_header);
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Type'), 'application/hal+json');
|
||||
|
||||
$this->drupalGet($node_uri);
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Type'), 'text/html; charset=UTF-8');
|
||||
$this->drupalGet($node_uri);
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
|
||||
$this->assertEqual($this->drupalGetHeader('Content-Type'), 'text/html; charset=UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
namespace Drupal\Tests\Core\Routing;
|
||||
|
||||
use Drupal\Core\ContentNegotiation;
|
||||
use Drupal\Core\Routing\AcceptHeaderMatcher;
|
||||
use Drupal\Tests\Core\Routing\RoutingFixtures;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
@ -41,7 +40,7 @@ class AcceptHeaderMatcherTest extends UnitTestCase {
|
|||
parent::setUp();
|
||||
|
||||
$this->fixtures = new RoutingFixtures();
|
||||
$this->matcher = new AcceptHeaderMatcher(new ContentNegotiation());
|
||||
$this->matcher = new AcceptHeaderMatcher();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,14 +49,14 @@ class AcceptHeaderMatcherTest extends UnitTestCase {
|
|||
* @see Drupal\Tests\Core\Routing\AcceptHeaderMatcherTest::testAcceptFiltering()
|
||||
*/
|
||||
public function acceptFilterProvider() {
|
||||
return array(
|
||||
return [
|
||||
// Check that JSON routes get filtered and prioritized correctly.
|
||||
array('application/json, text/xml;q=0.9', 'route_c', 'route_e'),
|
||||
['application/json, text/xml;q=0.9', 'json', 'route_c', 'route_e'],
|
||||
// Tests a JSON request with alternative JSON MIME type Accept header.
|
||||
array('application/x-json, text/xml;q=0.9', 'route_c', 'route_e'),
|
||||
['application/x-json, text/xml;q=0.9', 'json', 'route_c', 'route_e'],
|
||||
// Tests a standard HTML request.
|
||||
array('text/html, text/xml;q=0.9', 'route_e', 'route_c'),
|
||||
);
|
||||
['text/html, text/xml;q=0.9', 'html', 'route_e', 'route_c'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,6 +64,8 @@ class AcceptHeaderMatcherTest extends UnitTestCase {
|
|||
*
|
||||
* @param string $accept_header
|
||||
* The HTTP Accept header value of the request.
|
||||
* @param string $format
|
||||
* The request format.
|
||||
* @param string $included_route
|
||||
* The route name that should survive the filter and be ranked first.
|
||||
* @param string $excluded_route
|
||||
|
@ -72,11 +73,12 @@ class AcceptHeaderMatcherTest extends UnitTestCase {
|
|||
*
|
||||
* @dataProvider acceptFilterProvider
|
||||
*/
|
||||
public function testAcceptFiltering($accept_header, $included_route, $excluded_route) {
|
||||
public function testAcceptFiltering($accept_header, $format, $included_route, $excluded_route) {
|
||||
$collection = $this->fixtures->sampleRouteCollection();
|
||||
|
||||
$request = Request::create('path/two', 'GET');
|
||||
$request->headers->set('Accept', $accept_header);
|
||||
$request->setRequestFormat($format);
|
||||
$routes = $this->matcher->filter($collection, $request);
|
||||
$this->assertEquals(count($routes), 4, 'The correct number of routes was found.');
|
||||
$this->assertNotNull($routes->get($included_route), "Route $included_route was found when matching $accept_header.");
|
||||
|
@ -103,6 +105,8 @@ class AcceptHeaderMatcherTest extends UnitTestCase {
|
|||
|
||||
$request = Request::create('path/two', 'GET');
|
||||
$request->headers->set('Accept', 'application/json, text/xml;q=0.9');
|
||||
$request->setRequestFormat('json');
|
||||
$this->matcher->filter($routes, $request);
|
||||
$this->matcher->filter($routes, $request);
|
||||
$this->fail('No exception was thrown.');
|
||||
}
|
||||
|
|
|
@ -34,13 +34,6 @@ class RoutePreloaderTest extends UnitTestCase {
|
|||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The mocked content negotiator.
|
||||
*
|
||||
* @var \Drupal\Core\ContentNegotiation|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $negotiation;
|
||||
|
||||
/**
|
||||
* The tested preloader.
|
||||
*
|
||||
|
@ -54,10 +47,7 @@ class RoutePreloaderTest extends UnitTestCase {
|
|||
protected function setUp() {
|
||||
$this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
|
||||
$this->state = $this->getMock('\Drupal\Core\State\StateInterface');
|
||||
$this->negotiation = $this->getMockBuilder('\Drupal\Core\ContentNegotiation')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->preloader = new RoutePreloader($this->routeProvider, $this->state, $this->negotiation);
|
||||
$this->preloader = new RoutePreloader($this->routeProvider, $this->state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,12 +126,10 @@ class RoutePreloaderTest extends UnitTestCase {
|
|||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$request = new Request();
|
||||
$request->setRequestFormat('non-html');
|
||||
$event->expects($this->any())
|
||||
->method('getRequest')
|
||||
->will($this->returnValue($request));
|
||||
$this->negotiation->expects($this->once())
|
||||
->method('getContentType')
|
||||
->will($this->returnValue('non-html'));
|
||||
|
||||
$this->routeProvider->expects($this->never())
|
||||
->method('getRoutesByNames');
|
||||
|
@ -159,12 +147,10 @@ class RoutePreloaderTest extends UnitTestCase {
|
|||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$request = new Request();
|
||||
$request->setRequestFormat('html');
|
||||
$event->expects($this->any())
|
||||
->method('getRequest')
|
||||
->will($this->returnValue($request));
|
||||
$this->negotiation->expects($this->once())
|
||||
->method('getContentType')
|
||||
->will($this->returnValue('html'));
|
||||
|
||||
$this->routeProvider->expects($this->once())
|
||||
->method('getRoutesByNames')
|
||||
|
|
Loading…
Reference in New Issue