Apache / PHP возвращает код состояния HTTP 200 на страницах ошибок

Я использую PHP 5.4 на CentOS 7, и когда есть php-файл, который выдает ошибку (исключение или синтаксическую ошибку), он возвращает код состояния HTTP 200 вместо 500.

Как я могу получить это, чтобы возвратить 500 ошибок сервера, когда PHP встречает ошибку?

Я пытался просмотреть другие сообщения Stackoverflow, и все они, похоже, указывают на решения, связанные с возвратом собственного кода ошибки 500 (который, я считаю, должен быть нормальным поведением PHP сам по себе, без необходимости вручную запускать заголовок http, как по этой информации: PHP испускает 500 ошибок — где это задокументировано?) Это также указывает на Xdebug как на возможную проблему, но моя проблема сохраняется, даже когда я перестраиваю сервер без Xdebug.

У меня есть соответствующие настройки:

  • display_errors: on
  • display_startup_errors: on
  • error_reporting: -1 (это приводит к сообщению обо всех ошибках)

8

Решение

В соответствии с отчет об ошибках PHP, описанное здесь поведение связано с тем, как выставлен display_errors.

[2010-02-03 19:03 UTC] [email protected]

Причина, по которой ошибки отображения должны быть устранены, заключается в том, что отображаемые ошибки генерируют вывод, а вывод вызывает отправку заголовков. Боюсь, мы не можем ничего с этим поделать.

Таким образом, ответ на вопрос таков:

  • Когда display_errors включен, он вернется 200 всегда.
  • Когда display_errors выключен, он вернется 500,
12

Другие решения

Обходной путь к ошибке # 50921: используйте auto_prepend_file, чтобы установить код ответа http на 500, затем установите его на 200, когда вы знаете, что страница загружена. Репрезентативный, но не исчерпывающий пример:

# php.ini
auto_prepend_file = /path/to/auto_prepend_file.php

# auto_prepend_file.php
<?php http_response_code(500);

# index.php
<?php
register_shutdown_function(function () {
$error = error_get_last();
switch ($error['type'] ?? 0) {
case E_ERROR:
case E_PARSE:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_RECOVERABLE_ERROR:
file_put_contents('/path/to/log', $error['message'], FILE_APPEND);
http_response_code(500);
echo 'Something went horribly wrong.';
echo str_repeat(' ', 512);
break;
});

http_response_code(200);
require_once '/path/to/bootstrap.php';

Если index.php имеет ошибку сбоя, 500, установленный через файл автоподготовки, все еще будет выполняться. Там не будет никакого выхода, если display_error и / или display_startup_error включены, хотя. Если bootstrap.php или у любого из его иждивенцев есть ошибка сбоя, тогда функция выключения будет обрабатывать их.

Здесь все еще есть сценарии, которые необходимо учитывать:

  • Какой формат должен быть выведен? Проверьте ACCEPT заголовок или по умолчанию соответственно.
  • Что делать, если вывод уже запущен? Как вы прерываете поток, чтобы сигнализировать, что что-то пошло вбок?

Многое из этого зависит от того, насколько вы контролируете свою среду (например, пишите в конфигурацию уровня INI_SYSTEM) и как работает ваша инфраструктура (например, ob_start или нет).

Я подчеркну, что это просто обходной путь. Если в вашем файле auto_prepend_file есть ошибки разбора, вы вернетесь к исходной точке: PHP выдает код ошибки 200 состояния. Исправление двигателя, чтобы испустить 500 — единственный правильный способ разорвать этот цикл курицы и яйца.

1

Обратите внимание, что иногда это может быть до формата CustomLog в Apache. Например %>s («окончательный статус») может (правильно) выдать 403 в журнале доступа, тогда как просто %s может записать 200, даже если код состояния ответа был чем-то другим.

0
По вопросам рекламы [email protected]