Commit 3416124b authored by alexpott's avatar alexpott

Issue #2467759 by Mile23, andypost, Wim Leers, Berdir, Fabianx, Crell:...

Issue #2467759 by Mile23, andypost, Wim Leers, Berdir, Fabianx, Crell: Refactor drupal_process_attached() so it doesn't depend on drupal_add_http_header()
parent 3b3680e4
......@@ -278,70 +278,6 @@ function drupal_get_path($type, $name) {
return dirname(drupal_get_filename($type, $name));
}
/**
* Sets an HTTP response header for the current page.
*
* Note: When sending a Content-Type header, always include a 'charset' type,
* too. This is necessary to avoid security bugs (e.g. UTF-7 XSS).
*
* @param $name
* The HTTP header name, or the special 'Status' header name.
* @param $value
* The HTTP header value; if equal to FALSE, the specified header is unset.
* If $name is 'Status', this is expected to be a status code followed by a
* reason phrase, e.g. "404 Not Found".
* @param $append
* Whether to append the value to an existing header or to replace it.
*
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Symfony\Component\HttpFoundation\Response->headers->set().
* See https://www.drupal.org/node/2181523.
*/
function _drupal_add_http_header($name, $value, $append = FALSE) {
// The headers as name/value pairs.
$headers = &drupal_static('drupal_http_headers', array());
$name_lower = strtolower($name);
if ($value === FALSE) {
$headers[$name_lower] = FALSE;
}
elseif (isset($headers[$name_lower]) && $append) {
// Multiple headers with identical names may be combined using comma (RFC
// 2616, section 4.2).
$headers[$name_lower] .= ',' . $value;
}
else {
$headers[$name_lower] = $value;
}
}
/**
* Gets the HTTP response headers for the current page.
*
* @param $name
* An HTTP header name. If omitted, all headers are returned as name/value
* pairs. If an array value is FALSE, the header has been unset.
*
* @return
* A string containing the header value, or FALSE if the header has been set,
* or NULL if the header has not been set.
*
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
* Use \Symfony\Component\HttpFoundation\Response->headers->get().
* See https://www.drupal.org/node/2181523.
*/
function drupal_get_http_header($name = NULL) {
$headers = &drupal_static('drupal_http_headers', array());
if (isset($name)) {
$name = strtolower($name);
return isset($headers[$name]) ? $headers[$name] : NULL;
}
else {
return $headers;
}
}
/**
* Translates a string to the current language or to a given language.
*
......
......@@ -643,7 +643,7 @@ function drupal_process_attached(array $elements) {
call_user_func_array('_drupal_add_html_head_link', $args);
break;
case 'http_header':
call_user_func_array('_drupal_add_http_header', $args);
// @todo Remove validation in https://www.drupal.org/node/2477223
break;
default:
throw new \LogicException(sprintf('You are not allowed to use %s in #attached', $callback));
......
......@@ -107,8 +107,7 @@ public function processAttachments(AttachmentsInterface $response) {
$variables = $this->processAssetLibraries($attached, $placeholders);
// Handle all non-asset attachments. This populates drupal_get_html_head()
// and drupal_get_http_header().
// Handle all non-asset attachments. This populates drupal_get_html_head().
$all_attached = ['#attached' => $attached];
drupal_process_attached($all_attached);
......@@ -120,9 +119,10 @@ public function processAttachments(AttachmentsInterface $response) {
// Now replace the placeholders in the response content with the real data.
$this->renderPlaceholders($response, $placeholders, $variables);
// Finally set the headers on the response.
$headers = drupal_get_http_header();
$this->setHeaders($response, $headers);
// Finally set the headers on the response if any bubbled.
if (!empty($attached['http_header'])) {
$this->setHeaders($response, $attached['http_header']);
}
return $response;
}
......@@ -205,13 +205,17 @@ protected function renderPlaceholders(HtmlResponse $response, array $placeholder
* The headers to set.
*/
protected function setHeaders(HtmlResponse $response, array $headers) {
foreach ($headers as $name => $value) {
foreach ($headers as $values) {
$name = $values[0];
$value = $values[1];
$replace = !empty($values[2]);
// Drupal treats the HTTP response status code like a header, even though
// it really is not.
if ($name === 'status') {
if (strtolower($name) === 'status') {
$response->setStatusCode($value);
}
$response->headers->set($name, $value, FALSE);
$response->headers->set($name, $value, $replace);
}
}
......
<?php
/**
* @file
* Contains \Drupal\system\Tests\HttpKernel\HeadersResponseCodeRenderTest.
*/
namespace Drupal\system\Tests\HttpKernel;
use Drupal\simpletest\WebTestBase;
/**
* Tests rendering headers and response codes.
*
* @group Routing
*/
class HeadersResponseCodeRenderTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('httpkernel_test');
/**
* Tests the rendering of an array-based header and response code.
*/
public function testHeaderResponseCode() {
$this->drupalGet('/httpkernel-test/teapot');
$this->assertResponse(418);
$this->assertHeader('X-Test-Teapot', 'Teapot Mode Active');
$this->assertHeader('X-Test-Teapot-Replace', 'Teapot replaced');
$this->assertHeader('X-Test-Teapot-No-Replace', 'This value is not replaced,This one is added');
}
}
......@@ -4,3 +4,9 @@ httpkernel_test.empty:
_controller: '\Drupal\httpkernel_test\Controller\TestController::get'
requirements:
_access: 'TRUE'
httpkernel_test.teapot:
path: '/httpkernel-test/teapot'
defaults:
_controller: '\Drupal\httpkernel_test\Controller\TestController::teapot'
requirements:
_access: 'TRUE'
......@@ -21,4 +21,21 @@ public function get() {
return new Response();
}
/**
* Test special header and status code rendering.
*
* @return array
* A render array using features of the 'http_header' directive.
*/
public function teapot() {
$render = [];
$render['#attached']['http_header'][] = ['X-Test-Teapot-Replace', 'This value gets replaced'];
$render['#attached']['http_header'][] = ['X-Test-Teapot-Replace', 'Teapot replaced', TRUE];
$render['#attached']['http_header'][] = ['X-Test-Teapot-No-Replace', 'This value is not replaced'];
$render['#attached']['http_header'][] = ['X-Test-Teapot-No-Replace', 'This one is added', FALSE];
$render['#attached']['http_header'][] = ['X-Test-Teapot', 'Teapot Mode Active'];
$render['#attached']['http_header'][] = ['Status', "418 I'm a teapot."];
return $render;
}
}
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