Problem/Motivation

Headers set with drupal_add_http_header() will be ignored if they have a falsy value such as 0, "0", or " ". This makes it impossible to send (valid) headers like X-XSS-Protection: 0.

The problem is in drupal_send_headers(), which tries to skip headers that have been unset using drupal_add_http_header() but uses an over-aggressive test for that condition:

<?php
foreach ($headers as $name_lower => $value) {
  if (
$name_lower == 'status') {
   
header($_SERVER['SERVER_PROTOCOL'] . ' ' . $value);
  }
 
// Skip headers that have been unset.
 
elseif ($value) {
   
header($header_names[$name_lower] . ': ' . $value);
  }
}
?>

Proposed resolution

The documentation on drupal_add_http_header() says, "if [the $value parameter is] equal to FALSE, the specified header is unset". So let's only skip values of FALSE itself.

Remaining tasks

  • Test the latest patch.
  • Write a test.
  • Backport to d7.
  • Create a change notice?

User interface changes

None.

API changes

This changes the programming interface, if ever so slightly. Core itself isn't relying on the behavior anywhere (it isn't unsetting headers at all), but contrib modules could be. That's probably not a problem for d8, but this should probably be backported to d7, where contrib modules may be relying on it.

This issue may collide with #1400800: drupal_send_headers doesn't unset headers.

Original report by EdgarPE

I'm unsure if it's a functional bug or by design, but you as of 7.14 you can't add a HTTP header with drupal_add_http_header() for anonymous users in hook_boot or hook_init, even if page cache is disabled.

Test code:

<?php
function test_module_boot() {
  global
$user;
 
drupal_add_http_header('UserLoggedIn', $user->uid == 0 ? 0 : 1);
}
?>

The UserLoggedIn http response header is not present for not logged in users.

API page: http://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/drupa...

Enter a descriptive title (above) relating to drupal_add_http_header, then describe the problem you have found:

Files: 
CommentFileSizeAuthor
#9 drupal-falsy-http-header-values-1605040-9-D7.patch487 bytesmitron
PASSED: [[SimpleTest]]: [MySQL] 39,851 pass(es).
[ View ]
#6 drupal-falsy-http-header-values-1605040-6.patch507 bytesTravisCarden
PASSED: [[SimpleTest]]: [MySQL] 48,834 pass(es).
[ View ]
#4 drupal-falsy-http-header-values-1605040-4-d7-no-test.patch487 bytesTravisCarden
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch drupal-falsy-http-header-values-1605040-4-d7-no-test.patch. Unable to apply patch. See the log in the details link for more information.
[ View ]
#4 drupal-falsy-http-header-values-1605040-4.patch507 bytesTravisCarden
PASSED: [[SimpleTest]]: [MySQL] 48,873 pass(es).
[ View ]

Comments

Component:documentation» base system

Sounds like this is not a documentation issue?

Title:Can't add HTTP headers for anonymous users.HTTP header can't contain '0'

It's not about anonymous users. It's inpossible to add a http header containing only the character "0". I don't know if this is by design or bug.

Could it be that the problem is 0 or 1 are not in single quote?

look at comment#2 on below

http://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/drupa...

Issue summary:View changes

type

Title:HTTP header can't contain '0'drupal_send_headers() ignores headers with valid but falsy values
Version:7.x-dev» 8.x-dev
Issue tags:+Novice
StatusFileSize
new507 bytes
PASSED: [[SimpleTest]]: [MySQL] 48,873 pass(es).
[ View ]
new487 bytes
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch drupal-falsy-http-header-values-1605040-4-d7-no-test.patch. Unable to apply patch. See the log in the details link for more information.
[ View ]

Nope, this is a bug. See updated issue summary. Here's a patch. (And because I happen to need a quick fix for d7, I'm including a no-test patch for that, too.)

Status:Active» Needs review

StatusFileSize
new507 bytes
PASSED: [[SimpleTest]]: [MySQL] 48,834 pass(es).
[ View ]

Aw, nuts. I must not've named the no-test patch properly.* Here's the real patch again so as not to get a false failure from the test bot.

* Edit: To make the testbot skip a patch, end the filename with "do-not-test".

Status:Needs review» Reviewed & tested by the community

I have succesfully tested the patch.

Version:8.x-dev» 7.x-dev
Status:Reviewed & tested by the community» Patch (to be ported)
Issue tags:+Needs tests

Good catch. Committed to 8.x.

Moving to 7.x.

Also tagging this issue as 'needs tests'. Given that this is pretty small, we can add these later. Would be great if you could write some, Travis.

Thanks!

StatusFileSize
new487 bytes
PASSED: [[SimpleTest]]: [MySQL] 39,851 pass(es).
[ View ]

For 7.x

Status:Patch (to be ported)» Needs review

Status:Needs review» Reviewed & tested by the community

Looks good. Once this is committed I'll set the issue back to D8 and work on a test.

Title:drupal_send_headers() ignores headers with valid but falsy valuesdrupal_send_headers() ignores headers with valid but falsy values (followup for tests)
Version:7.x-dev» 8.x-dev
Category:bug» task
Status:Reviewed & tested by the community» Active
Issue tags:+7.22 release notes

Although a slight behavior change, this does seem to make sense and match what the documentation already said was happening.

Committed to 7.x (and added to CHANGELOG.txt) - thanks! http://drupalcode.org/project/drupal.git/commit/20a45b1

Back to Drupal 8 for the tests.

Issue tags:+needs backport to D7

Tests can be backported too.

Issue summary:View changes

Updated issue summary.