views:

324

answers:

2

I use PHP 5.2.9.

To see/log errors, at the beggining of my script I have:

error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 'On');
ini_set('log_errors', 'On');
ini_set('error_log', $_SERVER['DOCUMENT_ROOT'] . '/php.log');

But when I use the first of the next two lines, my script issue a HTTP 500 error, and nothing is displayed (except the 500 error) and nothing is logged in my php.log. If I use the second line instead of the first one, all is OK and the 304 is issued normally.

header('Not Modified', true, 304); //Crash php with 500 error
header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304); //Works OK
//In both case exit(); is called just after header().

Aren't these two lines equivalent (see link below)? Why the first version "crashes" my script?!

This is related to: http://stackoverflow.com/questions/2000092/header-use-in-php

Edit 1: This is the only log I can find:

'
69.70.84.xx - - [20/Jan/2010:15:54:06 -0600] "GET /framework2/ HTTP/1.1" 200 2968 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)"
69.70.84.xx - - [20/Jan/2010:15:54:08 -0600] "GET /foo/bar.js HTTP/1.1" 404 8642 "http://www.mydomain.com/framework2/" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)"
69.70.84.xx - - [20/Jan/2010:15:54:10 -0600] "GET /framework2/ HTTP/1.1" 500 8511 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)"
69.70.84.xx - - [20/Jan/2010:15:54:11 -0600] "GET /framework/mydomain_ajax-dom.js HTTP/1.1" 304 - "http://www.mydomain.com/framework2/" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)"
69.70.84.xx - - [20/Jan/2010:15:54:11 -0600] "GET /framework/templates/common/Reset.css HTTP/1.1" 304 - "http://www.mydomain.com/framework2/" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)"
69.70.84.xx - - [20/Jan/2010:15:54:11 -0600] "GET /framework/templates/common/Error.css HTTP/1.1" 304 - "http://www.mydomain.com/framework2/" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)"
69.70.84.xx - - [20/Jan/2010:15:54:11 -0600] "GET /framework/templates/common/Base.css HTTP/1.1" 304 - "http://www.mydomain.com/framework2/" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)"
69.70.84.xx - - [20/Jan/2010:15:54:11 -0600] "GET /images/Error-48.png HTTP/1.1" 304 - "http://www.mydomain.com/framework2/" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)"
'
  1. Line 1 is the document correctly served.
  2. Line 2 is the 404 of a dummy .js on my document.
  3. Line 3 is where the actual error occur (I hit refresh in my browser and my PHP issue the 304 header that crashes my script).
  4. Line 4, 5, 6, 7, 8 are caused by my custom error message (via .htaccess) that display the 500 error message.

Edit 2: I contacted Web host support to ask if I had access to more log they said no but on their side they have access to logs I can't see. My error was in there:

'backend: malformed header from script. Bad header=Not Modified: index.php'

So back to my question... Why on some hosts the first version don't work and on others it seems to be OK (even worse someone in the link above says that the second crashes while the first is OK)??

+2  A: 

You will want to check your web server error log, not your PHP error log in this case, to get more information about the crash.

loginx
In my "Error log" (I use cPanel) I only see 404s (File does not exist) and nothing else...
AlexV
Hmm i've never encountered an error 500 that didn't show up in the logs. Are you using NGINX as a front-end to apache or something like that? The 500 error has to be logged somewhere. Are the timestamps of your 404s recent? Most setups separate logfiles by domain or rotate them by timestamp, etc...
loginx
Don't know what NGINX is... My Web host uses cPanel (http://www.cpanel.net/). I can now confirm that PHP don't log any error and the main error log in cPanel don't seems to log anything either (the 404 timestamps match)...
AlexV
Both header() calls are technically correct. I've replicated them on my local workstation and ran a traffic capture. In both cases, the output was what was expected, with no Error 500, and here is what my local server sent me back: - For the first header() call: 1.241894 127.0.0.1 -> 127.0.0.1 HTTP HTTP/1.1 304 Not Modified - Second header() call: 53.971648 127.0.0.1 -> 127.0.0.1 HTTP HTTP/1.1 304 Not Modified You should perhaps contact your hosting provider and ask them if they have a gateway for HTTP requests that could be responsible for this.
loginx
Okay, the log you pasted *does* have the error 500, but it is an access log, not an error log. Can you look for the error log file? It should be a separate file.
loginx
On my local enviroment both header() calls work OK. Got the right log entry. Edited question to add info...
AlexV
I searched for header() bugs that fit the description on bugs.php.net and came back empty-handed. I recommend sticking to HTTP/1.1 303 Not Modified, as it is the most standard-compliant string, and perhaps open a bug report on bugs.php.net and ask in #php on irc.freenode.net
loginx
+2  A: 

No, those lines are not equivalent. The first will write an invalid header line. The documentation to the header function says:

header() is used to send a raw HTTP header.

And in the description of the string parameter:

There are two special-case header calls. The first is a header that starts with the string "HTTP/" (case is not significant), which will be used to figure out the HTTP status code to send.

In your case the value Not Modified does not start with HTTP/ and thus is not treated to set the HTTP status code but just a regular header field. But it is invalid as it does not has the form:

message-header = field-name ":" [ field-value ]

And that’s what the error log entry states. Not Modified is not a valid raw HTTP header.

The third parameter http_response_code is just to set the status code while setting a redirection to avoid two header calls like:

header('HTTP/1.1 301 Moved Permanently');
header('Location: http://example.com');

Instead of that you can simply write:

header('Location: http://example.com', true, 301);
Gumbo
So the first point of Ben James in following question is totally wrong? Point in question is "If you provide the 3rd argument, PHP will ignore the first string argument and send the correct response for the given number. This might make the first method less prone to programmer errors". http://stackoverflow.com/questions/2000092/header-use-in-php
AlexV
@AlexV: No, actually PHP will use the status code provided in the first parameter (it will also take the default status phrase based on that status code). So providing a value for the third parameter is pointless.
Gumbo
But why did they created this third parameter if it's worthless? In which cases does the third parameter is usefull?
AlexV
@AlexV: To set a header field *and* the status code at the same time. Like `header('Location: http://example.com', true, 301);` instead of what I wrote in my answer.
Gumbo