PHP: Як надіслати код відповіді HTTP?


Відповіді:


461

Я щойно знайшов це питання і подумав, що йому потрібна більш вичерпна відповідь:

Станом на PHP 5.4 є три методи для цього:

Складання власного коду відповіді (PHP> = 4.0)

header()Функція має спеціальний споживчої випадок , який визначає лінію відповіді HTTP і дозволяє замінити , що з призначеної для користувача один

header("HTTP/1.1 200 OK");

Однак для цього потрібне спеціальне лікування для (Fast) CGI PHP:

$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) == 'cgi')
    header("Status: 404 Not Found");
else
    header("HTTP/1.1 404 Not Found");

Примітка. Відповідно до протоколу HTTP RFC , причиною фрази може бути будь-який користувацький рядок (який відповідає стандарту), але для сумісності клієнтів я не рекомендую вкладати туди випадкову рядок.

Примітка: php_sapi_name() потрібен PHP 4.0.1

3-й аргумент до функції заголовка (PHP> = 4.3)

Очевидно, що існує декілька проблем при використанні першого варіанту. Найбільший з яких я думаю, це те, що він частково проаналізований PHP або веб-сервером і погано задокументований.

Починаючи з 4.3, у headerфункції є 3-й аргумент, який дозволяє вам дещо зручніше встановити код відповіді, але для його використання перший аргумент повинен бути не порожнім рядком. Ось два варіанти:

header(':', true, 404);
header('X-PHP-Response-Code: 404', true, 404);

Рекомендую 2-й . Перший робить роботу на всі браузери я тестував, але деякі незначні браузери або веб - сканери можуть мати проблеми з лінією заголовка , який містить тільки двокрапка. Назва поля заголовка у 2-му. варіант, звичайно, ні в якому разі не стандартизований і може бути змінений, я просто вибрав надію описову назву.

Функція коду http_response_code (PHP> = 5.4)

http_response_code()Функція була введена в PHP 5.4, і він зробив речі набагато простіше.

http_response_code(404);

Це все.

Сумісність

Ось функція, яку я приготував, коли мені потрібна була сумісність нижче 5.4, але хотіла функціонування "нової" http_response_codeфункції. Я вважаю, що PHP 4.3 - це більш ніж достатньо зворотної сумісності, але ви ніколи не знаєте ...

// For 4.3.0 <= PHP <= 5.4.0
if (!function_exists('http_response_code'))
{
    function http_response_code($newcode = NULL)
    {
        static $code = 200;
        if($newcode !== NULL)
        {
            header('X-PHP-Response-Code: '.$newcode, true, $newcode);
            if(!headers_sent())
                $code = $newcode;
        }       
        return $code;
    }
}

10
Я можу підтвердити, що header('X-PHP-Response-Code: 404', true, 404);працює правильно в PHP-FPM (FastCGI)
Josh

@dualed (1) не headers_sent()завжди буде правдою після виклику header()? (2) коли-небудь знайдете щось подібне до http_response_text () у світі 5.4? Принаймні старий заголовок () може впливати на текст після коду статусу.
Боб Штейн

@ BobStein-VisiBone (1) headers_sent() вірно, якщо ви не можете додати більше заголовків, оскільки вміст уже надіслано, а не якщо ви додали заголовок. (2) Вибачте, ні. Інші мови мають кращу підтримку
проіснували

1
@Послідьте, чому я не пропоную робити це те саме, чому я не пропоную лише двокрапку. PHP може поводитися з цим по-різному в усіх версіях, оскільки не визначено, що відбувається з таким "заголовком", він може повністю вийти з ладу - не встановивши ні заголовка, ні статусу, або він може додати недійсний заголовок (стандарт протоколу http 1.1 вимагає двокрапки )
протримався

8
Я витратив години, розуміючи, що http_response_code(і, можливо, більш загальна зміна заголовка) більше не працює після того, як ви echoщось зробите . Сподіваюся, це допомагає.
Нептіло

40

На жаль, я знайшов рішення, представлені @dualed, мають різні вади.

  1. Використання substr($sapi_type, 0, 3) == 'cgi'не є одним для виявлення швидкого CGI. Під час використання PHP-FPM FastCGI Process Manager php_sapi_name()повертає fpm не cgi

  2. Fasctcgi і php-fpm виявляють ще одну помилку, згадану @Josh - використання функціонує header('X-PHP-Response-Code: 404', true, 404);належним чином під PHP-FPM (FastCGI)

  3. header("HTTP/1.1 404 Not Found");може вийти з ладу, якщо протокол не є HTTP / 1.1 (тобто "HTTP / 1.0"). Поточний протокол повинен бути виявлений за допомогою $_SERVER['SERVER_PROTOCOL'](доступно з PHP 4.1.0

  4. Є щонайменше 2 випадки, коли виклик http_response_code()призводить до несподіваної поведінки:

    • Коли PHP стикається з кодом відповіді HTTP, який він не розуміє, PHP замінить код на той, який він знає, з тієї ж групи. Наприклад, "521 веб-сервер не працює" замінено на "500 внутрішніх помилок сервера". Багато інших незвичайних кодів відповідей з інших груп 2xx, 3xx, 4xx обробляються таким чином.
    • На сервері з функцією php-fpm та nginx http_response_code () МОЖЕТ змінити код як очікувалося, але не повідомлення. Це може призвести, наприклад, до дивного заголовка "404 ОК". Про цю проблему згадується також на веб-сайті PHP коментарем користувача http://www.php.net/manual/en/function.http-response-code.php#112423

Для довідки тут представлений повний перелік кодів статусу відповідей HTTP (цей список включає коди з IETF-стандартів Інтернету, а також інші RFC IETF. Багато з них наразі НЕ підтримується функцією PHP http_response_code): http: //uk.wikipedia .org / wiki / List_of_HTTP_status_codes

Ви можете легко протестувати цю помилку, зателефонувавши:

http_response_code(521);

Сервер надішле HTTP-код "500 внутрішніх помилок сервера", що призведе до несподіваних помилок, якщо у вас є, наприклад, спеціальна клієнтська програма, яка дзвонить на ваш сервер і очікує отримання додаткових кодів HTTP.


Моє рішення (для всіх версій PHP з 4.1.0):

$httpStatusCode = 521;
$httpStatusMsg  = 'Web server is down';
$phpSapiName    = substr(php_sapi_name(), 0, 3);
if ($phpSapiName == 'cgi' || $phpSapiName == 'fpm') {
    header('Status: '.$httpStatusCode.' '.$httpStatusMsg);
} else {
    $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
    header($protocol.' '.$httpStatusCode.' '.$httpStatusMsg);
}

Висновок

Реалізація http_response_code () не підтримує всі коди відповідей HTTP і може замінити вказаний код відповіді HTTP іншим з тієї ж групи.

Нова функція http_response_code () не вирішує всіх проблем, але найгірше вводить нові помилки.

Рішення "сумісності", яке пропонує @dualed, не працює, як очікувалося, принаймні за PHP-FPM.

Інші рішення, пропоновані @dualed, також мають різні помилки. Швидке виявлення CGI не обробляє PHP-FPM. Поточний протокол повинен бути виявлений.

Будь-які тести та коментарі цінуються.


21

оскільки PHP 5.4 ви можете використовувати http_response_code()для отримання та встановлення коду статусу заголовка.

ось приклад:

<?php

// Get the current response code and set a new one
var_dump(http_response_code(404));

// Get the new response code
var_dump(http_response_code());
?>

ось документ цієї функції на php.net:

http_response_code


На мій досвід, це найкраща відповідь.
Скруфі

Навіщо використовувати var_dump ()?
Томаш Гонсалес

Але чому var_dump () замість відлуння? Може результат не підходить для простого відлуння? Або навіть print_r (). var_dump () здається не таким адекватним для виробничого коду ...
Томаш Гонсалес

@TomasGonzalez це не велика справа, я просто хотів показати, що у ній, надрукувавши все з var_dump (), а ур правильно вони не важливі
Seyed Ali Roshan

Добре, я бачу. Що викликав мою увагу, це те, що в офіційних документах приклад використовує також var_dump (). Тож мені було цікаво про причину цього. Могло бути щось, чого мені не вистачало. php.net/manual/en/function.http-response-code.php
Томаш Гонсалес

10

Додайте цей рядок перед будь-яким виходом тіла, якщо ви не використовуєте буферизацію виводу.

header("HTTP/1.1 200 OK");

Замініть частину повідомлення ("ОК") на відповідне повідомлення, а код статусу - на відповідний код (404, 501 тощо)


2
Чи може повідомлення, яке ми поміщаємо (замінивши ОК), будь-що?
FMaz008

Це працювало для мене. Я працював над контактною формою на веб-сайті з PHP 5.3. І це рішення спрацювало на мене. Він дасть текст відповіді і цей HTTP-код для функції запиту AJAX, виконаної відмовою. Це все, чого я хотів.
Surjith SM

7

Якщо ви тут через те, що Wordpress дає 404 під час завантаження середовища, це має вирішити проблему:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
status_header( 200 );
//$wp_query->is_404=false; // if necessary

Проблема пов’язана з тим, що він надсилає заголовок Статус: 404 Не знайдено. Ви повинні це перекрити. Це також буде працювати:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");

заголовок ("HTTP / 1.1 200 ОК"); http_response_code (201); заголовок ("Статус: 200 Усі рум’яні"); // робота
alpc



2

Якщо ваша версія PHP не включає цю функцію:

<?php

function http_response_code($code = NULL) {
        if ($code !== NULL) {
            switch ($code) {
                case 100: $text = 'Continue';
                    break;
                case 101: $text = 'Switching Protocols';
                    break;
                case 200: $text = 'OK';
                    break;
                case 201: $text = 'Created';
                    break;
                case 202: $text = 'Accepted';
                    break;
                case 203: $text = 'Non-Authoritative Information';
                    break;
                case 204: $text = 'No Content';
                    break;
                case 205: $text = 'Reset Content';
                    break;
                case 206: $text = 'Partial Content';
                    break;
                case 300: $text = 'Multiple Choices';
                    break;
                case 301: $text = 'Moved Permanently';
                    break;
                case 302: $text = 'Moved Temporarily';
                    break;
                case 303: $text = 'See Other';
                    break;
                case 304: $text = 'Not Modified';
                    break;
                case 305: $text = 'Use Proxy';
                    break;
                case 400: $text = 'Bad Request';
                    break;
                case 401: $text = 'Unauthorized';
                    break;
                case 402: $text = 'Payment Required';
                    break;
                case 403: $text = 'Forbidden';
                    break;
                case 404: $text = 'Not Found';
                    break;
                case 405: $text = 'Method Not Allowed';
                    break;
                case 406: $text = 'Not Acceptable';
                    break;
                case 407: $text = 'Proxy Authentication Required';
                    break;
                case 408: $text = 'Request Time-out';
                    break;
                case 409: $text = 'Conflict';
                    break;
                case 410: $text = 'Gone';
                    break;
                case 411: $text = 'Length Required';
                    break;
                case 412: $text = 'Precondition Failed';
                    break;
                case 413: $text = 'Request Entity Too Large';
                    break;
                case 414: $text = 'Request-URI Too Large';
                    break;
                case 415: $text = 'Unsupported Media Type';
                    break;
                case 500: $text = 'Internal Server Error';
                    break;
                case 501: $text = 'Not Implemented';
                    break;
                case 502: $text = 'Bad Gateway';
                    break;
                case 503: $text = 'Service Unavailable';
                    break;
                case 504: $text = 'Gateway Time-out';
                    break;
                case 505: $text = 'HTTP Version not supported';
                    break;
                default:
                    exit('Unknown http status code "' . htmlentities($code) . '"');
                    break;
            }
            $protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
            header($protocol . ' ' . $code . ' ' . $text);
            $GLOBALS['http_response_code'] = $code;
        } else {
            $code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
        }
        return $code;
    }

1

Ми можемо отримати різні значення повернення від http_response_code через два різних середовища:

  1. Середовище веб-сервера
  2. CLI-середовище

У середовищі веб-сервера поверніть попередній код відповіді, якщо ви вказали код відповіді або коли ви не надали жодного коду відповіді, він буде надрукувати поточне значення. Значення за замовчуванням - 200 (ОК).

У CLI Environment істинним буде повернення, якщо ви вказали код відповіді, а false - якщо ви не вказали код відповіді.

Приклад середовища повернення веб-сервера коду Response_code:

var_dump(http_respone_code(500)); // int(200)
var_dump(http_response_code()); // int(500)

Приклад CLI-середовища оточуючого значення Response_code:

var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.