This is somewhat a re-issue (hope this won't sound annoying) as I found this problem already treated in some of his aspects here:

http://drupal.org/node/81752
http://drupal.org/node/64645
http://drupal.org/node/117756
http://drupal.org/node/6678

Going straight to the point, the root problem is that if PHP is using the CGI/FastCGI server API to interface itself with the web server, the HTTP status header will not be correctly set. This is due to the CGI specification which does not allow directly setting the HTTP status code
(see http://cgi-spec.golux.com/draft-coar-cgi-v11-03.txt, section 7.2.1.3).

This fact leds to multiple problems on a CGI-based system:
- [SEO] 404 pages, 403 pages and 503 pages have 200 OK status (bad, multiple URLs with the same content)
- [user] 401 pages do not cause the browser to show up the authentication dialog
- [user] 304 pages display nothing (I think this is the cause of many of the Blank pages - The White Screen of Death)
And so on...

Someone was pointing out this is not a Drupal bug but a PHP one, and that using CGI sapi is a poor choice under the performance aspect. I agree, but not always we can choose our system. I think the more Drupal is adaptable to system configurations the better is.
By the way, one of the most popular hosting solutions provider in Italy is using this configuration and I do not think I am the only one that has experienced this kind of problems.

I am providing a patch with my solution but I am pretty new to Drupal and I am sure that a real D-guy can find one better ;)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

plach’s picture

Priority: Critical » Normal

Sorry, I have just read the priority guidelines...

moshe weitzman’s picture

Status: Needs review » Needs work

Looks good.

Seems like you should use drupal_set_header within the new drupal_http_status().

plach’s picture

FileSize
0 bytes

this is exactly the kind of good advice I needed, thank you :)

here's the revised patch

plach’s picture

FileSize
6.95 KB

the revised patch

moshe weitzman’s picture

Status: Needs work » Needs review
drumm’s picture

Version: 5.2 » 6.x-dev

I would like to see this API change get into Drupal 6.x before consideration in 5.x.

Gábor Hojtsy’s picture

Status: Needs review » Needs work

- Please do the diff with diff -up, so we see where the changes take effect.
- Please observe coding standards about concatenation, eg. look inside drupal_http_status(), things shuld be like .' '. without the spaces)
- Also look at phpdoc formatting conventions and use that: one line function summary at the start, @param broken to multiple lines
- Your second drupal_http_status() call seems to be badly indented

Apart from these, the code generally looks good, and reminds me of the approach we took on php.net, when I was active in the webmaster team.

plach’s picture

FileSize
7.24 KB

I had to move the new drupal_http_status() function into bootstrap.inc in order to make 304 and 403 calls to work: in those cases the function (as the old code) uses the native header() function. I tested the patched code on both PHP Server APIs and it seems to work correctly. The tests were conducted on a plain 5.2 installation and on a plain HEAD installation.

@drumm: I am attaching a 6.x version of the patch.

@Gábor Hojtsy: I am using TortoiseCVS to make the patches and it actually uses diff -u. I corrected the source following your advices, I think it is ok now.

plach’s picture

Status: Needs work » Needs review
FileSize
7.26 KB

here is the 5.2 version

plach’s picture

FileSize
7.59 KB

and here is the diff -up version

plach’s picture

Any feedback out there?

plach’s picture

Again, anyone available to review the code?

plach’s picture

FileSize
7.59 KB

this an updated patch against the HEAD

Pancho’s picture

FileSize
4.65 KB

Still to be considered for D6.
Patch was broken by centralizing _db_error_page() to database.inc.
Rerolled the patch against HEAD. Didn't test it on CGI/Fast-CGI though.

Pancho’s picture

Slightly modified patch:

  • Renamed drupal_http_header() to drupal_set_http_header(), to be more descriptive.
  • Improved PHPdoc.
  • Minor code style.
Dave Reid’s picture

Status: Needs review » Needs work

This hasn't been bumped in a while, and after my attempt to get this fixed in #81752: Incorrect headers when using PHP as CGI, this would probably best be fixed by modifing the $_SERVER['SERVER_PROTOCOL'] variable to "Status:" within drupal_initialize_variables.

Dave Reid’s picture

Title: HTTP status header and CGI server api » Send valid HTTP status headers with PHP-CGI
Status: Needs work » Needs review
FileSize
906 bytes

Here's a patch that doesn't require a new function and only makes the change in the drupal_initialize_varibables function.

Anonymous’s picture

@Dave Reid: Is this patch for D7 as it indicates in the file name? If so, please change the version to indicate that.

Dave Reid’s picture

Version: 6.x-dev » 7.x-dev

Thanks earnie, I overlooked that.

Status: Needs review » Needs work

The last submitted patch failed testing.

Dave Reid’s picture

Status: Needs work » Needs review

Failed due to #74645: modify file_scan_directory to include a regex for the nomask.. Setting back to code needs review.

c960657’s picture

Isn't this fixed by adjusting cgi.rfc2616_headers? As you can see in the PHP source code, PHP already translates the status code into a Status: header (the linked source is that of PHP 5.2.0 - it has been updated several times since then).

If adjusting cgi.rfc2616_headers does not fix the problem, what is the PHP bug number? There are a number of bugs that sound like this that have already been fixed in recent PHP versions.

catch’s picture

Status: Needs review » Needs work

We need a comment here to the PHP bug number so we can remove the workaround later on when it's fixed (if it hasn't been already).

toomanypets’s picture

I just spent far too many hours tracking this problem down with D6.1 in a CGI/FastCGI environment. In this case users were getting 500's instead of 404's. I do not believe this is a PHP bug. While setting cgi.rfc2616_headers to 0 in php.ini resolves the problem, this workaround is impractical for many who do not have access to php.ini, or who can't override php.ini settings in an .htaccess file. Additionally, it seems to me that making the headers non-compliant is (a) counter-intuitive and (b) may break other applications.

Until a permanent fix is available, I hacked the /includes/common.inc file as suggested in many other posts, but this only addresses 404 problems:

function drupal_not_found() {
  if ((substr(php_sapi_name(),0,3)=='cgi')&&(ini_get('cgi.rfc2616_headers')=='1')) {
  drupal_set_header('Status: 404 Not Found');
    }
  else {
    drupal_set_header('HTTP/1.1 404 Not Found');
  }
kenorb’s picture

Similar problem.
The same website with the same code, but different responses:

GET /b1 HTTP/1.1
Host: host_with_php-cgi5

HTTP/1.1 404 Not Found
Date: Sat, 16 May 2009 03:43:06 GMT
Server: Apache/1.3.33
X-Powered-By: PHP/5.2.10-dev
Set-Cookie: SESSd62a0dd407ed7b169d8e935e80db7b4c=c2dbcf35da8c545d04866f51d241ecb9; expires=Mon, 08-Jun-2009 07:16:33 GMT; path=/; domain=. example.com
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Last-Modified: Sat, 16 May 2009 03:43:13 GMT
Cache-Control: store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Cache-Control: max-age=1209600
Expires: Sat, 30 May 2009 03:43:06 GMT
Location: http://example.com/new_location
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8

Tested with PHP 5.2.8, 5.2.9 and latest CVS snapshot

GET /b1 HTTP/1.1
Host: host_with_mod_php4

HTTP/1.1 301 Moved Permanently
Date: Sat, 16 May 2009 03:44:33 GMT
Server: Apache/1.3.33
Cache-Control: store, no-cache, must-revalidate
Expires: Sun, 19 Nov 1978 05:00:00 GMT
X-Powered-By: PHP/4.3.10
Set-Cookie: SESSdfdd77ce611e8b8fa2de6ee9fb8957a7=98af664c1448c514cf1f2c50e4c41c0e; expires=Mon, 08-Jun-2009 07:17:59 GMT; path=/; domain=.example.com
Last-Modified: Sat, 16 May 2009 03:44:39 GMT
Cache-Control: post-check=0, pre-check=0
Location: http://example.com/new_location
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8

There is something wrong with headers when using php-cgi
I even can't log in.

Tested on Drupal 6.11
Fix in #24 fixed only Page Not Found, but there are some problem with redirection as well.

Voting for patch #24 to be in the core.

kenorb’s picture

kenorb’s picture

Damien Tournoud’s picture

Status: Needs work » Closed (won't fix)

This is a configuration issue. When using PHP in CGI/FastCGI mode with CGI/1.1 compliant servers (Apache, Lighttpd, etc.) you *have* to set cgi.rfc2616-headers = 0 (which is the default).

The PHP manual has a wise word of caution:

Leave it set to 0 unless you know what you're doing.