diff --git a/core/core.services.yml b/core/core.services.yml index de88d8989d0cb633fd77bd2e5db44ccde95da7a0..966ed3d5c3a98905d090f99975a3d2063f4f0f94 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1059,7 +1059,7 @@ services: html_response.attachments_processor: class: Drupal\Core\Render\HtmlResponseAttachmentsProcessor tags: - arguments: ['@asset.resolver', '@config.factory', '@asset.css.collection_renderer', '@asset.js.collection_renderer', '@request_stack', '@renderer'] + arguments: ['@asset.resolver', '@config.factory', '@asset.css.collection_renderer', '@asset.js.collection_renderer', '@request_stack', '@renderer', '@module_handler'] html_response.subscriber: class: Drupal\Core\EventSubscriber\HtmlResponseSubscriber tags: diff --git a/core/includes/common.inc b/core/includes/common.inc index b11a6a681c294d70350c02ed09820c002b336e15..38a2a3ddbb46a364a81ab14ee80af2503796dc69 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -147,62 +147,6 @@ */ const LOCALE_PLURAL_DELIMITER = "\03"; -/** - * Adds output to the HEAD tag of the HTML page. - * - * This function can be called as long as the headers aren't sent. Pass no - * arguments (or NULL for both) to retrieve the currently stored elements. - * - * @param $data - * A renderable array. If the '#type' key is not set then 'html_tag' will be - * added as the default '#type'. - * @param $key - * A unique string key to allow implementations of hook_html_head_alter() to - * identify the element in $data. Required if $data is not NULL. - * - * @return - * An array of all stored HEAD elements. - * - * @see \Drupal\Core\Render\Element\HtmlTag::preRenderHtmlTag() - * - * @deprecated in Drupal 8.0.x, will be removed before Drupal 8.0.0 - * Use #attached on render arrays. - */ -function _drupal_add_html_head($data = NULL, $key = NULL) { - $stored_head = &drupal_static(__FUNCTION__, array()); - - if (isset($data) && isset($key)) { - if (!isset($data['#type'])) { - $data['#type'] = 'html_tag'; - } - $stored_head[$key] = $data; - } - return $stored_head; -} - -/** - * Retrieves output to be displayed in the HEAD tag of the HTML page. - * - * @param bool $render - * If TRUE render the HEAD elements, otherwise return just the elements. - * - * @return string|array - * Return the rendered HTML head or the elements itself. - * - * @deprecated in Drupal 8.0.x, will be removed before Drupal 8.0.0 - * Use #attached on render arrays. - */ -function drupal_get_html_head($render = TRUE) { - $elements = _drupal_add_html_head(); - \Drupal::moduleHandler()->alter('html_head', $elements); - if ($render) { - return \Drupal::service('renderer')->renderPlain($elements); - } - else { - return $elements; - } -} - /** * Prepares a 'destination' URL query parameter for use with url(). * @@ -476,39 +420,6 @@ function base_path() { return $GLOBALS['base_path']; } -/** - * Adds a LINK tag with a distinct 'rel' attribute to the page's HEAD. - * - * This function can be called as long the HTML header hasn't been sent, which - * on normal pages is up through the preprocess step of _theme('html'). Adding - * a link will overwrite a prior link with the exact same 'rel' and 'href' - * attributes. - * - * @param $attributes - * Associative array of element attributes including 'href' and 'rel'. - * @param $header - * Optional flag to determine if a HTTP 'Link:' header should be sent. - * - * @deprecated in Drupal 8.0.x, will be removed before Drupal 8.0.0 - * Use #attached on render arrays. - */ -function _drupal_add_html_head_link($attributes, $header = FALSE) { - $element = array( - '#tag' => 'link', - '#attributes' => $attributes, - ); - $href = $attributes['href']; - - if ($header) { - // Also add a HTTP header "Link:". - $href = '<' . Html::escape($attributes['href']) . '>;'; - unset($attributes['href']); - $element['#attached']['http_header'][] = array('Link', $href . drupal_http_header_attributes($attributes), TRUE); - } - - _drupal_add_html_head($element, 'html_head_link:' . $attributes['rel'] . ':' . $href); -} - /** * Deletes old cached CSS files. * @@ -607,39 +518,8 @@ function drupal_js_defaults($data = NULL) { * 'bare_html_page_renderer' service. */ function drupal_process_attached(array $elements) { - // Asset attachments are handled by \Drupal\Core\Asset\AssetResolver. - foreach (array('library', 'drupalSettings') as $type) { - unset($elements['#attached'][$type]); - } - - // Add additional types of attachments specified in the render() structure. - foreach ($elements['#attached'] as $callback => $options) { - foreach ($elements['#attached'][$callback] as $args) { - // Limit the amount allowed entries. - switch ($callback) { - case 'html_head': - call_user_func_array('_drupal_add_html_head', $args); - break; - case 'feed': - $args = [[ - 'href' => $args[0], - 'rel' => 'alternate', - 'title' => $args[1], - 'type' => 'application/rss+xml', - ]]; - call_user_func_array('_drupal_add_html_head_link', $args); - break; - case 'html_head_link': - call_user_func_array('_drupal_add_html_head_link', $args); - break; - case 'http_header': - // @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)); - } - } - } + $build['#attached'] = $elements['#attached']; + \Drupal::service('renderer')->render($build); } /** diff --git a/core/lib/Drupal/Core/Render/AttachmentsResponseProcessorInterface.php b/core/lib/Drupal/Core/Render/AttachmentsResponseProcessorInterface.php index 82577630f15f56b2c2451b3b3db345b5f3bcbeb3..6067a862571183f356d1821577a55e7bba6d3f46 100644 --- a/core/lib/Drupal/Core/Render/AttachmentsResponseProcessorInterface.php +++ b/core/lib/Drupal/Core/Render/AttachmentsResponseProcessorInterface.php @@ -9,6 +9,8 @@ /** * Defines an interface for processing attachments of responses that have them. * + * @see \Drupal\Core\Ajax\AjaxResponse + * @see \Drupal\Core\Ajax\AjaxResponseAttachmentsProcessor * @see \Drupal\Core\Render\HtmlResponse * @see \Drupal\Core\Render\HtmlResponseAttachmentsProcessor */ @@ -17,13 +19,38 @@ interface AttachmentsResponseProcessorInterface { /** * Processes the attachments of a response that has attachments. * + * Libraries, JavaScript settings, feeds, HTML <head> tags, HTML <head> links, + * HTTP headers, and the HTTP status code are attached to render arrays using + * the #attached property. The #attached property is an associative array, + * where the keys are the attachment types and the values are the attached + * data. For example: + * + * @code + * $build['#attached']['library'][] = [ + * 'library' => ['core/jquery'] + * ]; + * $build['#attached']['http_header'][] = [ + * ['Content-Type', 'application/rss+xml; charset=utf-8'], + * ]; + * @endcode + * + * The available keys are: + * - 'library' (asset libraries) + * - 'drupalSettings' (JavaScript settings) + * - 'feed' (RSS feeds) + * - 'html_head' (tags in HTML <head>) + * - 'html_head_link' (<link> tags in HTML <head>) + * - 'http_header' (HTTP headers and status code) + * * @param \Drupal\Core\Render\AttachmentsInterface $response - * The response to process the attachments for. + * The response to process. * * @return \Drupal\Core\Render\AttachmentsInterface * The processed response. * * @throws \InvalidArgumentException + * Thrown when the $response parameter is not the type of response object + * the processor expects. */ public function processAttachments(AttachmentsInterface $response); diff --git a/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php b/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php index 19edef13808ad2a1cef53fcab5100ace2c9d2b0b..6104b0ae512680fa5b9dc423bb6d409898532d3e 100644 --- a/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php +++ b/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php @@ -11,11 +11,23 @@ use Drupal\Core\Asset\AttachedAssets; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Form\EnforcedResponseException; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Render\BubbleableMetadata; +use Drupal\Component\Utility\Html; +use Drupal\Component\Utility\SafeMarkup; use Symfony\Component\HttpFoundation\RequestStack; /** * Processes attachments of HTML responses. * + * This class is used by the rendering service to process the #attached part of + * the render array, for HTML responses. + * + * To render attachments to HTML for testing without a controller, use the + * 'bare_html_page_renderer' service to generate a + * Drupal\Core\Render\HtmlResponse object. Then use its getContent(), + * getStatusCode(), and/or the headers property to access the result. + * * @see template_preprocess_html() * @see \Drupal\Core\Render\AttachmentsResponseProcessorInterface * @see \Drupal\Core\Render\BareHtmlPageRenderer @@ -66,6 +78,13 @@ class HtmlResponseAttachmentsProcessor implements AttachmentsResponseProcessorIn */ protected $renderer; + /** + * The module handler service. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + /** * Constructs a HtmlResponseAttachmentsProcessor object. * @@ -81,14 +100,17 @@ class HtmlResponseAttachmentsProcessor implements AttachmentsResponseProcessorIn * The request stack. * @param \Drupal\Core\Render\RendererInterface $renderer * The renderer. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler service. */ - public function __construct(AssetResolverInterface $asset_resolver, ConfigFactoryInterface $config_factory, AssetCollectionRendererInterface $css_collection_renderer, AssetCollectionRendererInterface $js_collection_renderer, RequestStack $request_stack, RendererInterface $renderer) { + public function __construct(AssetResolverInterface $asset_resolver, ConfigFactoryInterface $config_factory, AssetCollectionRendererInterface $css_collection_renderer, AssetCollectionRendererInterface $js_collection_renderer, RequestStack $request_stack, RendererInterface $renderer, ModuleHandlerInterface $module_handler) { $this->assetResolver = $asset_resolver; $this->config = $config_factory->get('system.performance'); $this->cssCollectionRenderer = $css_collection_renderer; $this->jsCollectionRenderer = $js_collection_renderer; $this->requestStack = $request_stack; $this->renderer = $renderer; + $this->moduleHandler = $module_handler; } /** @@ -117,27 +139,67 @@ public function processAttachments(AttachmentsInterface $response) { return $e->getResponse(); } + // Get a reference to the attachments. $attached = $response->getAttachments(); + // Send a message back if the render array has unsupported #attached types. + $unsupported_types = array_diff( + array_keys($attached), + ['html_head', 'feed', 'html_head_link', 'http_header', 'library', 'html_response_attachment_placeholders', 'placeholders', 'drupalSettings'] + ); + if (!empty($unsupported_types)) { + throw new \LogicException(sprintf('You are not allowed to use %s in #attached.', implode(', ', $unsupported_types))); + } + // Get the placeholders from attached and then remove them. $attachment_placeholders = $attached['html_response_attachment_placeholders']; unset($attached['html_response_attachment_placeholders']); $variables = $this->processAssetLibraries($attached, $attachment_placeholders); - // Handle all non-asset attachments. This populates drupal_get_html_head(). - $all_attached = ['#attached' => $attached]; - drupal_process_attached($all_attached); + // Since we can only replace content in the HTML head section if there's a + // placeholder for it, we can safely avoid processing the render array if + // it's not present. + if (!empty($attachment_placeholders['head'])) { + // 'feed' is a special case of 'html_head_link'. We process them into + // 'html_head_link' entries and merge them. + if (!empty($attached['feed'])) { + $attached = BubbleableMetadata::mergeAttachments( + $attached, + $this->processFeed($attached['feed']) + ); + } + // 'html_head_link' is a special case of 'html_head' which can be present + // as a head element, but also as a Link: HTTP header depending on + // settings in the render array. Processing it can add to both the + // 'html_head' and 'http_header' keys of '#attached', so we must address + // it before 'html_head'. + if (!empty($attached['html_head_link'])) { + // Merge the processed 'html_head_link' into $attached so that its + // 'html_head' and 'http_header' values are present for further + // processing. + $attached = BubbleableMetadata::mergeAttachments( + $attached, + $this->processHtmlHeadLink($attached['html_head_link']) + ); + } - // Get HTML head elements - if present. - if (isset($attachment_placeholders['head'])) { - $variables['head'] = drupal_get_html_head(FALSE); + // Now we can process 'html_head', which contains both 'feed' and + // 'html_head_link'. + if (!empty($attached['html_head'])) { + $html_head = $this->processHtmlHead($attached['html_head']); + // Invoke hook_html_head_alter(). + $this->moduleHandler->alter('html_head', $html_head); + // Store the result in $variables so it can be inserted into the + // placeholder. + $variables['head'] = $html_head; + } } // Now replace the attachment placeholders. $this->renderHtmlResponseAttachmentPlaceholders($response, $attachment_placeholders, $variables); - // Finally set the headers on the response if any bubbled. + // Set the HTTP headers and status code on the response if any bubbled. if (!empty($attached['http_header'])) { $this->setHeaders($response, $attached['http_header']); } @@ -243,6 +305,9 @@ protected function processAssetLibraries(array $attached, array $placeholders) { /** * Renders HTML response attachment placeholders. * + * This is the last step where all of the attachments are placed into the + * response object's contents. + * * @param \Drupal\Core\Render\HtmlResponse $response * The HTML response to update. * @param array $placeholders @@ -268,7 +333,13 @@ protected function renderHtmlResponseAttachmentPlaceholders(HtmlResponse $respon * @param \Drupal\Core\Render\HtmlResponse $response * The HTML response to update. * @param array $headers - * The headers to set. + * The headers to set, as an array. The items in this array should be as + * follows: + * - The header name. + * - The header value. + * - (optional) Whether to replace a current value with the new one, or add + * it to the others. If the value is not replaced, it will be appended, + * resulting in a header like this: 'Header: value1,value2' */ protected function setHeaders(HtmlResponse $response, array $headers) { foreach ($headers as $values) { @@ -281,8 +352,105 @@ protected function setHeaders(HtmlResponse $response, array $headers) { if (strtolower($name) === 'status') { $response->setStatusCode($value); } - $response->headers->set($name, $value, $replace); + else { + $response->headers->set($name, $value, $replace); + } + } + } + + /** + * Ensure proper key/data order and defaults for renderable head items. + * + * @param array $html_head + * The ['#attached']['html_head'] portion of a render array. + * + * @return array + * The ['#attached']['html_head'] portion of a render array with #type of + * html_tag added for items without a #type. + */ + protected function processHtmlHead(array $html_head) { + $head = []; + foreach ($html_head as $item) { + list($data, $key) = $item; + if (!isset($data['#type'])) { + $data['#type'] = 'html_tag'; + } + $head[$key] = $data; + } + return $head; + } + + /** + * Transform a html_head_link array into html_head and http_header arrays. + * + * html_head_link is a special case of html_head which can be present as + * a link item in the HTML head section, and also as a Link: HTTP header, + * depending on options in the render array. Processing it can add to both the + * html_head and http_header sections. + * + * @param array $html_head_link + * The 'html_head_link' value of a render array. Each head link is specified + * by a two-element array: + * - An array specifying the attributes of the link. + * - A boolean specifying whether the link should also be a Link: HTTP + * header. + * + * @return array + * An ['#attached'] section of a render array. This allows us to easily + * merge the results with other render arrays. The array could contain the + * following keys: + * - http_header + * - html_head + */ + protected function processHtmlHeadLink(array $html_head_link) { + $attached = []; + + foreach ($html_head_link as $item) { + $attributes = $item[0]; + $should_add_header = isset($item[1]) ? $item[1] : FALSE; + + $element = array( + '#tag' => 'link', + '#attributes' => $attributes, + ); + $href = $attributes['href']; + $attached['html_head'][] = [$element, 'html_head_link:' . $attributes['rel'] . ':' . $href]; + + if ($should_add_header) { + // Also add a HTTP header "Link:". + $href = '<' . Html::escape($attributes['href'] . '>'); + unset($attributes['href']); + $attached['http_header'][] = ['Link', $href . drupal_http_header_attributes($attributes), TRUE]; + } + } + return $attached; + } + + /** + * Transform a 'feed' attachment into an 'html_head_link' attachment. + * + * The RSS feed is a special case of 'html_head_link', so we just turn it into + * one. + * + * @param array $attached_feed + * The ['#attached']['feed'] portion of a render array. + * + * @return array + * An ['#attached']['html_head_link'] array, suitable for merging with + * another 'html_head_link' array. + */ + protected function processFeed($attached_feed) { + $html_head_link = []; + foreach($attached_feed as $item) { + $feed_link = [ + 'href' => $item[0], + 'rel' => 'alternate', + 'title' => empty($item[1]) ? '' : $item[1], + 'type' => 'application/rss+xml', + ]; + $html_head_link[] = [$feed_link, FALSE]; } + return ['html_head_link' => $html_head_link]; } } diff --git a/core/lib/Drupal/Core/Render/theme.api.php b/core/lib/Drupal/Core/Render/theme.api.php index e9144cfd3d8132347ad23fe93b8a560c15590d52..313922479dcb42e413d2206e1d54218fbc6a99fd 100644 --- a/core/lib/Drupal/Core/Render/theme.api.php +++ b/core/lib/Drupal/Core/Render/theme.api.php @@ -375,7 +375,10 @@ * Libraries, JavaScript settings, feeds, HTML <head> tags and HTML <head> links * are attached to elements using the #attached property. The #attached property * is an associative array, where the keys are the attachment types and the - * values are the attached data. For example: + * values are the attached data. + * + * The #attached property can also be used to specify HTTP headers and the + * response status code. * * The #attached property allows loading of asset libraries (which may contain * CSS assets, JavaScript assets, and JavaScript setting assets), JavaScript @@ -386,10 +389,11 @@ * @code * $build['#attached']['library'][] = 'core/jquery'; * $build['#attached']['drupalSettings']['foo'] = 'bar'; - * $build['#attached']['feed'][] = ['aggregator/rss', $this->t('Feed title')]; + * $build['#attached']['feed'][] = [$url, $this->t('Feed title')]; * @endcode * - * See drupal_process_attached() for additional information. + * See \Drupal\Core\Render\AttachmentsResponseProcessorInterface for additional + * information. * * See \Drupal\Core\Asset\LibraryDiscoveryParser::parseLibraryInfo() for more * information on how to define libraries. diff --git a/core/modules/book/book.module b/core/modules/book/book.module index 3a48671500b834efa960db654189af7ed246b1b5..dc543fc785e937a3aa45e2c5ead96162727efe4c 100644 --- a/core/modules/book/book.module +++ b/core/modules/book/book.module @@ -466,7 +466,6 @@ function template_preprocess_book_export_html(&$variables) { $variables['base_url'] = $base_url; $variables['language'] = $language_interface; $variables['language_rtl'] = ($language_interface->getDirection() == LanguageInterface::DIRECTION_RTL); - $variables['head'] = drupal_get_html_head(); // HTML element attributes. $attributes = array(); diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php index 309bb2b5b56643a94afec6d32c4a03c9d9428f79..0e2bf5c75b79bc8599a893dcf333e831a58267de 100644 --- a/core/modules/simpletest/src/KernelTestBase.php +++ b/core/modules/simpletest/src/KernelTestBase.php @@ -586,7 +586,6 @@ protected function registerStreamWrapper($scheme, $class, $type = StreamWrapperI */ protected function render(array &$elements) { $content = $this->container->get('renderer')->renderRoot($elements); - drupal_process_attached($elements); $this->setRawContent($content); $this->verbose('<pre style="white-space: pre-wrap">' . Html::escape($content)); return $content; diff --git a/core/modules/system/src/Tests/Common/AddFeedTest.php b/core/modules/system/src/Tests/Common/AddFeedTest.php index 1aa6a444c50b4b5f83722ba72d4c6f1b889c1d6b..0620051873109046fadf72501143f3a39aa65cc0 100644 --- a/core/modules/system/src/Tests/Common/AddFeedTest.php +++ b/core/modules/system/src/Tests/Common/AddFeedTest.php @@ -68,7 +68,6 @@ function testBasicFeedAddNoTitle() { ); // Glean the content from the response object. $this->setRawContent($response->getContent()); - // Assert that the content contains the RSS links we specified. foreach ($urls as $description => $feed_info) { $this->assertPattern($this->urlToRSSLinkPattern($feed_info['url'], $feed_info['title']), format_string('Found correct feed header for %description', array('%description' => $description))); diff --git a/core/modules/system/src/Tests/Common/RenderTest.php b/core/modules/system/src/Tests/Common/RenderTest.php index 94ad431e8768669aa7f7d65412486b6882097c32..df0278b82d25576f3b776c68317c037ab5df1194 100644 --- a/core/modules/system/src/Tests/Common/RenderTest.php +++ b/core/modules/system/src/Tests/Common/RenderTest.php @@ -55,12 +55,13 @@ function testDrupalRenderThemePreprocessAttached() { /** * Tests that we get an exception when we try to attach an illegal type. */ - public function testDrupalProcessAttached() { + public function testProcessAttached() { // Specify invalid attachments in a render array. $build['#attached']['library'][] = 'core/drupal.states'; $build['#attached']['drupal_process_states'][] = []; + $renderer = $this->container->get('bare_html_page_renderer'); try { - $this->render($build); + $renderer->renderBarePage($build, '', $this->container->get('theme.manager')->getActiveTheme()->getName()); $this->fail("Invalid #attachment 'drupal_process_states' allowed"); } catch (\LogicException $e) { diff --git a/core/modules/system/src/Tests/HttpKernel/HeadersResponseCodeRenderTest.php b/core/modules/system/src/Tests/HttpKernel/HeadersResponseCodeRenderTest.php deleted file mode 100644 index 7a81a0d4919ed0f8e6badd02117352392a93c321..0000000000000000000000000000000000000000 --- a/core/modules/system/src/Tests/HttpKernel/HeadersResponseCodeRenderTest.php +++ /dev/null @@ -1,37 +0,0 @@ -<?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'); - } - -} diff --git a/core/modules/system/tests/modules/httpkernel_test/httpkernel_test.routing.yml b/core/modules/system/tests/modules/httpkernel_test/httpkernel_test.routing.yml index 8f5762a52d1ce0a63814b72175d3eda4b9eedf04..7de4338c755c35929154d66c6dcea0a9b2738112 100644 --- a/core/modules/system/tests/modules/httpkernel_test/httpkernel_test.routing.yml +++ b/core/modules/system/tests/modules/httpkernel_test/httpkernel_test.routing.yml @@ -4,9 +4,3 @@ 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' diff --git a/core/modules/system/tests/modules/httpkernel_test/src/Controller/TestController.php b/core/modules/system/tests/modules/httpkernel_test/src/Controller/TestController.php index 5730080da5293d250660237d50b76d2f08565fd9..1699594444e8c96cb15050046a210121c588f935 100644 --- a/core/modules/system/tests/modules/httpkernel_test/src/Controller/TestController.php +++ b/core/modules/system/tests/modules/httpkernel_test/src/Controller/TestController.php @@ -21,21 +21,4 @@ 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; - } - }