Commit 70b73015 authored by Dries's avatar Dries

Issue #1846582 by klausi, katbailey: restrict data retrieving routes to media type.

parent f03337ad
......@@ -493,6 +493,7 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
$schema_store = drupal_container()->get('keyvalue')->get('system.schema');
$module_config = config('system.module');
$disabled_config = config('system.module.disabled');
$module_filenames = drupal_container()->getParameter('container.modules');
foreach ($module_list as $module) {
// Only process modules that are not already enabled.
$enabled = $module_config->get("enabled.$module") !== NULL;
......@@ -516,11 +517,12 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
system_list_reset();
module_implements_reset();
_system_update_bootstrap_status();
$module_filenames[$module] = drupal_get_filename('module', $module);
// Update the kernel to include it.
// @todo The if statement is here because install_begin_request() creates
// a container without a kernel. It probably shouldn't.
if ($kernel = drupal_container()->get('kernel', ContainerInterface::NULL_ON_INVALID_REFERENCE)) {
$kernel->updateModules(module_list(), array($module => drupal_get_filename('module', $module)));
$kernel->updateModules(module_list(), $module_filenames);
}
// Refresh the schema to include it.
drupal_get_schema(NULL, TRUE);
......
<?php
/**
* @file
* Contains Drupal\jsonld\EventSubscriber\JsonldSubscriber.
*/
namespace Drupal\jsonld\EventSubscriber;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Subscribes to the kernel request event to add JSON-LD media formats.
*/
class JsonldSubscriber implements EventSubscriberInterface {
/**
* Registers JSON-LD 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('drupal_jsonld', 'application/vnd.drupal.ld+json');
$request->setFormat('jsonld', 'application/ld+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;
}
}
......@@ -58,5 +58,8 @@ public function build(ContainerBuilder $container) {
$container->register("serializer.encoder.{$format}", $encoder_class)
->addTag('encoder', array('priority' => $priority));
}
$container->register('jsonld.subscriber', 'Drupal\jsonld\EventSubscriber\JsonldSubscriber')
->addTag('event_subscriber');
}
}
......@@ -53,37 +53,41 @@ public function permissions() {
*/
public function routes() {
$collection = new RouteCollection();
$name = strtr($this->plugin_id, ':', '.');
$prefix = strtr($this->plugin_id, ':', '/');
$path_prefix = strtr($this->plugin_id, ':', '/');
$route_name = strtr($this->plugin_id, ':', '.');
$methods = $this->requestMethods();
foreach ($methods as $method) {
$lower_method = strtolower($method);
// Only expose routes where the HTTP request method exists on the plugin.
if (method_exists($this, $lower_method)) {
// Special case for resource creation via POST: Add a route that does
// not require an ID.
if ($method == 'POST') {
$route = new Route("/$prefix", array(
'_controller' => 'Drupal\rest\RequestHandler::handle',
'_plugin' => $this->plugin_id,
'id' => NULL,
), array(
// The HTTP method is a requirement for this route.
'_method' => $method,
'_permission' => "restful $lower_method $this->plugin_id",
));
}
else {
$route = new Route("/$prefix/{id}", array(
'_controller' => 'Drupal\rest\RequestHandler::handle',
'_plugin' => $this->plugin_id,
), array(
// The HTTP method is a requirement for this route.
'_method' => $method,
'_permission' => "restful $lower_method $this->plugin_id",
));
$route = new Route("/$path_prefix/{id}", array(
'_controller' => 'Drupal\rest\RequestHandler::handle',
// Pass the resource plugin ID along as default property.
'_plugin' => $this->plugin_id,
), array(
// The HTTP method is a requirement for this route.
'_method' => $method,
'_permission' => "restful $lower_method $this->plugin_id",
));
switch ($method) {
case 'POST':
// POST routes do not require an ID in the URL path.
$route->setPattern("/$path_prefix");
$route->addDefaults(array('id' => NULL));
break;
case 'GET':
case 'HEAD':
// Restrict GET and HEAD requests to the media type specified in the
// HTTP Accept headers.
// @todo Replace hard coded format here with available formats.
$route->addRequirements(array('_format' => 'drupal_jsonld'));
break;
}
$collection->add("$name.$method", $route);
$collection->add("$route_name.$method", $route);
}
}
......
......@@ -52,7 +52,7 @@ public function get($id = NULL) {
if (!empty($record)) {
// Serialization is done here, so we indicate with NULL that there is no
// subsequent serialization necessary.
$response = new ResourceResponse(NULL, 200, array('Content-Type' => 'application/json'));
$response = new ResourceResponse(NULL, 200, array('Content-Type' => 'application/vnd.drupal.ld+json'));
// @todo remove hard coded format here.
$response->setContent(drupal_json_encode($record));
return $response;
......
......@@ -50,16 +50,16 @@ public function testWatchdog() {
$account = $this->drupalCreateUser(array('restful get dblog'));
$this->drupalLogin($account);
$response = $this->httpRequest("dblog/$id", 'GET', NULL, 'application/json');
$response = $this->httpRequest("dblog/$id", 'GET', NULL, 'application/vnd.drupal.ld+json');
$this->assertResponse(200);
$this->assertHeader('content-type', 'application/json');
$this->assertHeader('content-type', 'application/vnd.drupal.ld+json');
$log = drupal_json_decode($response);
$this->assertEqual($log['wid'], $id, 'Log ID is correct.');
$this->assertEqual($log['type'], 'rest_test', 'Type of log message is correct.');
$this->assertEqual($log['message'], 'Test message', 'Log message text is correct.');
// Request an unknown log entry.
$response = $this->httpRequest("dblog/9999", 'GET', NULL, 'application/json');
$response = $this->httpRequest("dblog/9999", 'GET', NULL, 'application/vnd.drupal.ld+json');
$this->assertResponse(404);
$this->assertEqual($response, 'Not Found', 'Response message is correct.');
}
......
......@@ -41,7 +41,8 @@ protected function httpRequest($url, $method, $body = NULL, $format = 'applicati
$curl_options = array(
CURLOPT_HTTPGET => TRUE,
CURLOPT_URL => url($url, $options),
CURLOPT_NOBODY => FALSE
CURLOPT_NOBODY => FALSE,
CURLOPT_HTTPHEADER => array('Accept: ' . $format),
);
break;
......
......@@ -59,8 +59,12 @@ public function testRead() {
// checked in serialization tests.
$this->assertEqual($data['uuid'][LANGUAGE_DEFAULT][0]['value'], $entity->uuid(), 'Entity UUID is correct');
// Try to read the entity with an unsupported media format.
$response = $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'GET', NULL, 'application/wrongformat');
$this->assertResponse(415);
// Try to read an entity that does not exist.
$response = $this->httpRequest('entity/' . $entity_type . '/9999', 'GET', NULL, 'application/ld+json');
$response = $this->httpRequest('entity/' . $entity_type . '/9999', 'GET', NULL, 'application/vnd.drupal.ld+json');
$this->assertResponse(404);
$this->assertEqual($response, 'Entity with ID 9999 not found', 'Response message is correct.');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment