PHP: jak wysłać kod odpowiedzi HTTP?

Mam skrypt PHP, który musi odpowiadać kodami odpowiedzi HTTP (kody stanu), np. HTTP 200 OK, albo jakiś kod 4XX lub 5xx.

Jak mogę to zrobić w PHP?

Author: hakre, 2010-07-15

7 answers

Właśnie znalazłem to pytanie i pomyślałem, że potrzebuje bardziej wyczerpującej odpowiedzi:

Począwszy od PHP 5.4 istnieją trzy metody, aby to osiągnąć:

Samodzielne składanie kodu odpowiedzi (PHP > = 4.0)

The header() funkcja ma specjalny przypadek użycia, który wykrywa linię odpowiedzi HTTP i pozwala zastąpić ją niestandardową

header("HTTP/1.1 200 OK");
Jednak wymaga to specjalnego traktowania dla (szybkiego)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");

Uwaga: Zgodnie z HTTP RFC, reason phrase może być dowolnym niestandardowym ciągiem znaków (zgodnym ze standardem), ale ze względu na kompatybilność z klientem nie zalecam umieszczania tam losowego ciągu znaków.

Uwaga: php_sapi_name() wymaga PHP 4.0.1

Trzeci argument do funkcji nagłówka (PHP > = 4.3)

Jest oczywiście kilka problemów podczas używania tego pierwszego wariantu. Największym z nich jest to, że jest to częściowo przetwarzane przez PHP lub serwer WWW i słabo udokumentowane.

Od wersji 4.3, funkcja header ma trzeci argument, który pozwala na wygodne ustawienie kodu odpowiedzi, ale użycie go wymaga, aby pierwszy argument był niepustym ciągiem znaków. Oto dwie opcje:

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

Polecam ten drugi . Pierwsza Działa {[30] } na wszystkich przeglądarkach, które przetestowałem, ale niektóre drobne przeglądarki lub roboty internetowe mogą mieć problem z linią nagłówka, która zawiera tylko dwukropek. Na Nazwa pola nagłówka w 2. wariant nie jest oczywiście standaryzowany w żaden sposób i można go modyfikować, po prostu wybrałem miejmy nadzieję opisową nazwę.

Http_response_code function (PHP >= 5.4)

The http_response_code() funkcja została wprowadzona w PHP 5.4 i sprawiła, że sprawy były dużo łatwiejsze.

http_response_code(404);
To wszystko.

Zgodność

Oto funkcja, którą przygotowałem, gdy potrzebowałem kompatybilności poniżej 5.4, ale chciałem funkcjonalność funkcja "Nowa" http_response_code. Wierzę, że PHP 4.3 to więcej niż wystarczająca kompatybilność wsteczna, ale nigdy nie wiadomo...

// 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;
    }
}
 363
Author: dualed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-18 12:46:40

Niestety znalazłem rozwiązania przedstawione przez @ dualed mają różne wady.

  1. Użycie substr($sapi_type, 0, 3) == 'cgi' nie jest enogh do wykrywania szybkich CGI. Gdy używasz PHP-FPM FastCGI Process Manager, php_sapi_name() zwraca fpm nie cgi

  2. Fasctcgi i php-fpm ujawniają kolejny błąd wymieniony przez @ Josh-używanie header('X-PHP-Response-Code: 404', true, 404); działa poprawnie pod PHP-FPM (FastCGI)

  3. header("HTTP/1.1 404 Not Found"); może zawieść, gdy protokół nie jest HTTP / 1.1 (tj. 'HTTP/1.0'). Aktualny protokół musi zostać wykryty za pomocą $_SERVER['SERVER_PROTOCOL'] (dostępne od PHP 4.1.0

  4. Istnieją co najmniej 2 przypadki, gdy wywołanie http_response_code() powoduje nieoczekiwane zachowanie:

    • gdy PHP napotka kod odpowiedzi HTTP, którego nie rozumie, PHP zastąpi kod z tej samej grupy. Na przykład "521 Web server is down" jest zastępowany przez "500 Internal Server Error". Wiele innych nietypowych kodów odpowiedzi z innych grup 2xx, 3xx, 4xx są traktowane w ten sposób.
    • na serwerze z php-fpm i nginx funkcja http_response_code () może zmienić kod zgodnie z oczekiwaniami, ale nie Wiadomość. Może to spowodować na przykład dziwny nagłówek "404 OK". Ten problem jest również wspomniany na stronie PHP przez komentarz użytkownika http://www.php.net/manual/en/function.http-response-code.php#112423

W celach informacyjnych tutaj znajduje się pełna lista kodów statusu odpowiedzi HTTP (lista ta zawiera kody ze standardów internetowych IETF, jak również innych RFC IETF. Wielu z nich nie jest obecnie obsługiwane przez funkcję PHP http_response_code): http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Możesz łatwo przetestować ten błąd, wywołując:

http_response_code(521);

Serwer wyśle kod odpowiedzi HTTP" 500 Internal Server Error", powodując nieoczekiwane błędy, jeśli na przykład masz niestandardową aplikację kliencką wywołującą Twój serwer i oczekującą dodatkowych kodów HTTP.


Moje rozwiązanie (dla wszystkich wersji PHP od 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);
}

Wniosek

Implementacja Http_response_code () nie obsługuje wszystkich kodów odpowiedzi HTTP i może zastąpić podany kod odpowiedzi HTTP innym z tej samej grupy.

Nowa funkcja http_response_code() nie rozwiązuje wszystkich problemów, ale pogarsza sytuację wprowadzając nowe błędy.

Rozwiązanie "kompatybilności" oferowane przez @ dualed nie działa zgodnie z oczekiwaniami, przynajmniej pod PHP-FPM.

The inne rozwiązania oferowane przez @ dualed również mają różne błędy. Szybkie wykrywanie CGI nie obsługuje PHP-FPM. Aktualny protokół musi zostać wykryty.

Wszelkie testy i komentarze są mile widziane.

 29
Author: Grigore Madalin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-27 21:54:38

Dodaj tę linię przed dowolnym wyjściem ciała, jeśli nie używasz buforowania wyjścia.

header("HTTP/1.1 200 OK");

Zastąp część wiadomości ('OK') odpowiednią wiadomością, a kod stanu Twoim kodem (404, 501 itd.)

 7
Author: sparkey0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-15 18:27:02

Od wersji PHP 5.4 możesz używać http_response_code() do get I set header status code.

Oto przykład:

<?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());
?>

Oto dokument tej funkcji w php.net:

Http_response_code

 7
Author: Seyed Ali Roshan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-06 15:54:17

Z funkcją nagłówka . W sekcji dotyczącej pierwszego parametru znajduje się przykład.

 5
Author: Quentin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-15 18:26:35

Jeśli jesteś tutaj, ponieważ WordPress daje 404 podczas ładowania środowiska, powinno to rozwiązać problem:

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

Problem jest spowodowany wysłaniem nagłówka Status: 404 Not Found. Musisz to obejść. To również zadziała:

define('WP_USE_THEMES', false);
require('../wp-blog-header.php');
header("HTTP/1.1 200 OK");
header("Status: 200 All rosy");
 5
Author: jaggedsoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-13 08:21:31
header("HTTP/1.1 200 OK");
http_response_code(201);

Http_response_code (200); nie działa, ponieważ test alert 404 https://developers.google.com/speed/pagespeed/insights/

 1
Author: alpc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-21 15:59:20