PHP (Apache) безмолвно преобразует HTTP 429 и другие в 500

Я только что обнаружил странность в методе PHP header(), молча преобразовывая некоторые из моих статусов в 500. Так как мне не повезло найти упоминание об этом поведении в различных веб-поисках, я добавляю это здесь в надежде спасти другие - некоторое обострение, но также спросить, нашел ли кто-нибудь лучшее обходное решение (с PHP или Zend1), чем я придумал.

Учитывая простой PHP script как:

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

Я бы ожидал получить что-то вроде:

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

Вместо этого он фактически возвращает:

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

Добавляя к тайне, в моем журнале ошибок apache нет событий, и журнал доступа показывает правильный код состояния (таким образом, отличный от того, что было отправлено в браузер):

$IP - - [18/Jul/2013:16:31:34 -0700] "GET /test/429.php HTTP/1.1" 429 11 "-" "curl/7.30.0"

Все отлично работает при тестировании со многими другими кодами состояния, такими как 401, 420, 426.

Все работает отлично, если я явный и отправляю заголовок ( "HTTP/1.1 429 слишком много запросов" ); Это было бы полезным обходным решением, за исключением того, что я использую Zend Framework, а метод setHttpResponseCode ожидает целое число, которое он использует в качестве третьего параметра для функции php header().

С тех пор я обнаружил, что он, похоже, относится к статусам, добавленным в RFC 6585 (см. https://github.com/php/php-src/pull/274), хотя я немного запутались, почему такие статусы, как 426, работают, когда они явно не присутствуют в исходном коде 5.4.14 и 5.4.16 (две версии, которые я тестировал), но не функциональные, такие как 429.

Update:

Как показали ответы, это в основном проблема Apache, а не PHP, я обновил заголовок соответственно. Самое интересное, похоже, что это исправлено только в некоторых версиях Apache (без видимой согласованности между старым и новым). Я считаю, что проблема с восходящим потоком находится здесь: https://issues.apache.org/bugzilla/show_bug.cgi?id=44995

Ответ 1

Это Apache, на 99% уверен, я не могу найти его прямо в нем docs, но я могу сделать это из теста ниже (версия Apache 2.2.22)

Добавьте это в свою конфигурацию:

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 также кажется недавним добавлением в rfc6585, статус: предлагается, дата: апрель 2012 года. Один год для HTTP RFC... просто ребенок в моем опыте. Добавьте к этому процесс получения его в Apache, а затем в своих репозиториях пакетов... Ну, вы можете попробовать Apache 2.4...

Ответ 2

Возможно, это ваша конфигурация SAPI. В прошлый раз, когда я тестировал нечто подобное, вывод выглядел так:

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

Что в вашем случае работает для меня хорошо (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