Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Add HTTP Headers Using #attached in Drupal 7

Parent Feed: 

Today, I discovered an undocumented but cool feature in Drupal 7. If you’ve been doing any work with the Drupal 7 Form API, you probably know about the #attached property that you can add to any element. The #attached property allows you to associate JavaScript files, special settings to go into Drupal.settings, CSS files, or require the loading of a library specified in a hook_library call. It’s a really handy way to avoid having to find an appropriate place and use a bunch of drupal_add_js() or drupal_add_css() calls in your code.

What I discovered today is that you can also attach HTTP Headers to be set in the page response when an element is rendered. First, let’s look at where it is being used in drupal core:

    /**
     * Returns elements that are always displayed in the HEAD tag of the HTML page.
     */

    function _drupal_default_html_head() {
      // Add default elements. Make sure the Content-Type comes first because the
      // IE browser may be vulnerable to XSS via encoding attacks from any content
      // that comes before this META tag, such as a TITLE tag.
      $elements[‘system_meta_content_type’] = array(
        ‘#type’ => ‘html_tag’,
        ‘#tag’ => ‘meta’,
        ‘#attributes’ => array(
          ‘http-equiv’ => ‘Content-Type’,
          ‘content’ => ‘text/html; charset=utf-8′,
        ),
        // Security: This always has to be output first.
        ‘#weight’ => -1000,
      );
      // Show Drupal and the major version number in the META GENERATOR tag.
      // Get the major version.
      list($version, ) = explode(‘.’, VERSION);
      $elements[‘system_meta_generator’] = array(
        ‘#type’ => ‘html_tag’,
        ‘#tag’ => ‘meta’,
        ‘#attributes’ => array(
          ‘name’ => ‘Generator’,
          ‘content’ => ‘Drupal ‘ . $version . ‘ (http://drupal.org)’,
        ),
      );
      // Also send the generator in the HTTP header.
      $elements[‘system_meta_generator’][‘#attached’][‘drupal_add_http_header’][] = array(‘X-Generator’, $elements[‘system_meta_generator’][‘#attributes’][‘content’]);
      return $elements;
    }

This function is adding a <meta> tag that identifies that this page was generated using Drupal 7. It then adds to the #attached property the following (reformatted for readability):

    ‘#attached’ => array(
      ‘drupal_add_http_header’ => array(
        array(‘X-Generator’, $elements[‘system_meta_generator’][‘#attributes’][‘content’])
      ),
    )

And that’s it! If you inspect the HTTP Headers sent to you when you load a page, you’ll see an X-Generator header that identifies this site as being built with Drupal 7.

Web Inspector of HTTP Response Headers

So how might you use this when you’re writing your own custom code?

Here’s a hypothetical scenario where I think this might come in handy:

Imagine that you have created your own CAPTCHA system and it gets added to forms that are available to anonymous visitors. For performance you want most of your pages to be cached by Drupal and by your visitor’s browsers, so you have caching enabled. However, you want to make sure that your visitor’s browsers don’t cache the page with an old CAPTCHA on it. An easy way to address this would be to add an HTTP Cache-Control header whenever your CAPTCHA gets rendered.

Here’s some imaginary code:

    $form[‘captcha’] = array(
      ‘#type’ => ‘captcha’,
      ‘#attached’ => array(
        ‘drupal_add_http_header’ => array(
          array(‘Cache-Control’, ‘no-cache, no-store, must-revalidate’)
        ),
      ),
    );

Now, whenever the form with your CAPTCHA element gets rendered, Drupal will send Cache-Control headers to instruct your browser (or a reverse proxy cache like Varnish) not to cache that page.

Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web