PHP (Apache) silently converting HTTP 429 and othe

2019-02-09 02:49发布

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

2条回答
手持菜刀,她持情操
2楼-- · 2019-02-09 03:09

It's perhaps your SAPI configuraiton. Last time I tested something similar, the conclusion looked like this:

<?php
header('HTTP/ 429 Too Many Requests', false, 429);
echo "Too Many Requests\n";

Which in your case works still well for me (Apache 2.2 / FCGI / Windows):

>curl -i "http://local.example.com/header-test.php"
HTTP/1.1 429 Too Many Requests
Date: Thu, 18 Jul 2013 23:49:09 GMT
Server: Apache/2.2.22 (Win32) mod_fcgid/2.3.6
X-Powered-By: PHP/5.4.13
Transfer-Encoding: chunked
Content-Type: text/html

Too Many Requests
查看更多
该账号已被封号
3楼-- · 2019-02-09 03:28

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:

ErrorDocument 429 Aaargh to heavy

Restart:

$ sudo /etc/init.d/apache2 restart
Syntax error on line 6 of /etc/apache2/conf.d/localized-error-pages:
Unsupported HTTP response code 429
Action 'configtest' failed.
The Apache error log may have more information.
   ...fail!

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...

查看更多
登录 后发表回答