I just discovered an oddity in PHP's header() method silently converting some of my statuses to 500. Since I had no luck in finding mention of this behavior in various web searches, I'm adding this here in the hope of saving others some aggravation, but also to ask if anyone has discovered a better workaround (either with PHP or Zend1) than I've come up with.
Given a simple PHP script like:
<?php
header('HTTP/1.1 429');
echo "Too Many Requests\n";
I would expect to receive something like:
HTTP/1.1 429
Date: Thu, 18 Jul 2013 22:19:45 GMT
Content-Length: 11
Content-Type: text/html; charset=UTF-8
Too Many Requests
Instead, it actually returns:
HTTP/1.1 500 Internal Server Error
Date: Thu, 18 Jul 2013 22:19:45 GMT
Content-Length: 11
Content-Type: text/html; charset=UTF-8
Too Many Requests
Adding to the mystery, there are no events in my apache error log, and the access log shows the correct status code (thus different from what got sent to the browser):
$IP - - [18/Jul/2013:16:31:34 -0700] "GET /test/429.php HTTP/1.1" 429 11 "-" "curl/7.30.0"
Everything works fine when testing with many other status codes like 401, 420, 426.
Everything also works fine if I am explicit and send header('HTTP/1.1 429 Too Many Requests'); This would be a useful workaround except that I'm using Zend Framework and its setHttpResponseCode method expects an integer, which it uses as the third parameter to php's header() function.
I've since discovered that it seems to apply specifically to statuses added in RFC 6585 (see https://github.com/php/php-src/pull/274), though I'm a little confused why statuses like 426 work when they're clearly not present in the source code for 5.4.14 and 5.4.16 (the two versions I've tested against) but non-functional ones like 429 are.
Update:
As answers have indicated, this is mostly an Apache issue, not PHP, I've updated the title accordingly. Most interesting seems to be that this is fixed only in certain versions of Apache (with no apparent consistency between old and new). I believe the upstream issue in question is here: https://issues.apache.org/bugzilla/show_bug.cgi?id=44995
It's perhaps your SAPI configuraiton. Last time I tested something similar, the conclusion looked like this:
Which in your case works still well for me (Apache 2.2 / FCGI / Windows):
It's Apache, 99% sure, I can't find it direcly in it's docs, but I can infer it from the test below (Apache version 2.2.22)
Add this in your config:
Restart:
429
also seems a recent addition in rfc6585, status: proposed, date: April 2012. One year old for HTTP RFCs is... just a baby in my experience. Add to that the process of getting it in Apache, and then in your package repositories... Well, you could try Apache 2.4...