Commit 77661397 authored by alexpott's avatar alexpott

Issue #2752325 by Wim Leers, marthinal, dawehner, ericpugh: Automatically...

Issue #2752325 by Wim Leers, marthinal, dawehner, ericpugh: Automatically provide HEAD support when a REST resource supports GET
parent e0af7555
......@@ -62,6 +62,21 @@ public static function create(ContainerInterface $container) {
public function handle(RouteMatchInterface $route_match, Request $request) {
$method = strtolower($request->getMethod());
// Symfony is built to transparently map HEAD requests to a GET request. In
// the case of the REST module's RequestHandler though, we essentially have
// our own light-weight routing system on top of the Drupal/symfony routing
// system. So, we have to do the same as what the UrlMatcher does: map HEAD
// requests to the logic for GET. This also guarantees response headers for
// HEAD requests are identical to those for GET requests, because we just
// return a GET response. Response::prepare() will transform it to a HEAD
// response at the very last moment.
// @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4
// @see \Symfony\Component\Routing\Matcher\UrlMatcher::matchCollection()
// @see \Symfony\Component\HttpFoundation\Response::prepare()
if ($method === 'head') {
$method = 'get';
}
$resource_config_id = $route_match->getRouteObject()->getDefault('_rest_resource_config');
/** @var \Drupal\rest\RestResourceConfigInterface $resource_config */
$resource_config = $this->resourceStorage->load($resource_config_id);
......
......@@ -2,6 +2,7 @@
namespace Drupal\rest\Tests;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Url;
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
......@@ -19,7 +20,7 @@ class PageCacheTest extends RESTTestBase {
*
* @var array
*/
public static $modules = array('hal', 'rest', 'entity_test');
public static $modules = array('hal');
/**
* The 'serializer' service.
......@@ -135,4 +136,31 @@ public function testConfigChangePageCache() {
}
}
/**
* Tests HEAD support when a REST resource supports GET.
*/
public function testHeadSupport() {
user_role_grant_permissions('anonymous', ['view test entity', 'restful get entity:entity_test']);
// Create an entity programatically.
$this->entityCreate('entity_test')->save();
$url = Url::fromUri('internal:/entity_test/1?_format=' . $this->defaultFormat);
$this->enableService('entity:entity_test', 'GET');
$this->httpRequest($url, 'HEAD', NULL, $this->defaultMimeType);
$this->assertResponse(200, 'HTTP response code is correct.');
$this->assertHeader('X-Drupal-Cache', 'MISS');
$this->assertResponseBody('');
$response = $this->httpRequest($url, 'GET', NULL, $this->defaultMimeType);
$this->assertResponse(200, 'HTTP response code is correct.');
$this->assertHeader('X-Drupal-Cache', 'HIT');
$this->assertCacheTag('config:rest.resource.entity.entity_test');
$this->assertCacheTag('entity_test:1');
$data = Json::decode($response);
$this->assertEqual($data['type'][0]['value'], 'entity_test');
}
}
......@@ -55,9 +55,28 @@ public function testRead() {
// Create an entity programmatically.
$entity = $this->entityCreate($entity_type);
$entity->save();
// Verify that it exists: use a HEAD request.
$this->httpRequest($this->getReadUrl($entity), 'HEAD');
$this->assertResponseBody('');
$head_headers = $this->drupalGetHeaders();
// Read it over the REST API.
$response = $this->httpRequest($this->getReadUrl($entity), 'GET');
$get_headers = $this->drupalGetHeaders();
$this->assertResponse('200', 'HTTP response code is correct.');
// Verify that the GET and HEAD responses are the same, that the only
// difference is that there's no body.
unset($get_headers['date']);
unset($head_headers['date']);
unset($get_headers['content-length']);
unset($head_headers['content-length']);
unset($get_headers['x-drupal-dynamic-cache']);
unset($head_headers['x-drupal-dynamic-cache']);
$this->assertIdentical($get_headers, $head_headers);
$this->assertResponse('200', 'HTTP response code is correct.');
$this->assertHeader('content-type', $this->defaultMimeType);
$data = Json::decode($response);
// Only assert one example property here, other properties should be
......
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