PHP:HTTP応答コードを送信する方法?


254

私は、HTTP 200 OKなどのHTTP応答コード(status-codes)、またはいくつかの4XXまたは5XXコードで応答を行う必要があるPHPスクリプトを持っています。

PHPでこれを行うにはどうすればよいですか?

回答:


461

私はこの質問を見つけ、より包括的な答えが必要だと思いました:

PHP 5.4以降、これを行う方法は3つあります。

自分で応答コードを組み立てる(PHP> = 4.0)

このheader()関数には、HTTP応答行を検出し、それをカスタム行に置き換えることができる特別なユースケースがあります

header("HTTP/1.1 200 OK");

ただし、これには(高速)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 4.0.1php_sapi_name()が必要です

ヘッダー関数の3番目の引数(PHP> = 4.3)

最初のバリアントを使用する場合、明らかにいくつかの問題があります。私が思う最大のものは、PHPまたはWebサーバーによって部分的に解析され、十分に文書化されていないことです。

4.3以降、header関数には3番目の引数があり、応答コードを多少快適に設定できますが、この関数を使用するには、最初の引数を空でない文字列にする必要があります。2つのオプションがあります。

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

2本目をお勧めします。最初のもの、テストしたすべてのブラウザーで機能しますが、一部のマイナーブラウザーまたはWebクローラーは、コロンのみを含むヘッダー行に問題がある可能性があります。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
PHP-FPM(FastCGI)でheader('X-PHP-Response-Code: 404', true, 404);正しく機能することを確認できます
Josh

@dualed(1)をheaders_sent()呼び出した直後は、常に正しいとは限りませんheader()か?(2)5.4の世界でhttp_response_text()のようなものを見つけたことがありますか?少なくとも古いheader()は、ステータスコードの後のテキストに影響を与える可能性があります。
ボブスタイン

@ BobStein-VisiBone (1) headers_sent()は、ヘッダーが追加されていない場合ではなく、コンテンツが既に送信されているためにヘッダーを追加できない場合にtrueになります。(2)すみません。ただし、他の言語の方がサポートが優れています
2013

1
@Perry私がこれをすることを勧めない理由は、私がコロンのみのものを勧めない理由と同じです。PHPは、このような「ヘッダー」で何が発生するかが定義されていないため、バージョン全体でこれを異なる方法で処理する可能性があります。完全に失敗する可能性があります。ヘッダーまたはステータスを設定しないか、無効なヘッダーを追加する可能性があります(http 1.1プロトコル標準にコロンが必要です)
2014

8
http_response_codeあなたがecho何かをした後、私は何時間も費やして(そしてもっと一般的にはヘッダーを変更することは)機能しないことに気づきました。それが役に立てば幸い。
Neptilo 2014年

40

残念ながら、@ dualedによって提示されたソリューションにはさまざまな欠陥があることがわかりました。

  1. を使用してsubstr($sapi_type, 0, 3) == 'cgi'高速CGIを検出することはできません。PHP-FPM FastCGI Process Managerを使用すると、php_sapi_name()cgiではなくfpmが返される

  2. Fasctcgiとphp-fpmは、@ Joshによって言及された別のバグを公開します-PHP header('X-PHP-Response-Code: 404', true, 404);-FPM(FastCGI)での使用は正しく機能します

  3. header("HTTP/1.1 404 Not Found");プロトコルがHTTP / 1.1でない場合(つまり、「HTTP / 1.0」)は失敗する可能性があります。現在のプロトコルは$_SERVER['SERVER_PROTOCOL'](PHP 4.1.0以降で使用可能)を使用して検出する必要があります。

  4. 呼び出しhttp_response_code()が予期しない動作をする場合、少なくとも2つのケースがあります。

    • PHPが理解できないHTTP応答コードに遭遇すると、PHPは同じグループの既知のコードにコードを置き換えます。たとえば、「521 Web server is down」は「500 Internal Server Error」に置き換えられます。他のグループ2xx、3xx、4xxからの他の多くの一般的でない応答コードは、この方法で処理されます。
    • php-fpmおよびnginx http_response_code()関数を備えたサーバーでは、コードを予想どおりに変更できますが、メッセージは変更できません。これにより、たとえば、奇妙な「404 OK」ヘッダーが生じる可能性があります。この問題は、ユーザーのコメントhttp://www.php.net/manual/en/function.http-response-code.php#112423によってPHP Webサイトでも言及されています

ご参考までに、HTTP応答ステータスコードの完全なリストがあります(このリストには、IETFインターネット標準とその他のIETF RFCのコードが含まれています。それらの多くは、現在、PHP http_response_code関数でサポートされていません):http://en.wikipedia .org / wiki / List_of_HTTP_status_codes

このバグは次のように呼び出すことで簡単にテストできます。

http_response_code(521);

たとえば、カスタムクライアントアプリケーションがサーバーを呼び出し、いくつかの追加のHTTPコードを予期している場合、サーバーは "500内部サーバーエラー" HTTP応答コードを送信し、予期しないエラーが発生します。


私の解決策(4.1.0以降のすべてのPHPバージョン):

$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


私の経験では、これが最良の答えです。
だらしない2018年

なぜvar_dump()を使うのですか?
Tomas Gonzalez

しかし、なぜechoではなくvar_dump()なのでしょうか。結果は単純なエコーには適していませんか?または、print_r()です。var_dump()は本番用コードには適切ではないようです...
Tomas Gonzalez

@TomasGonzalezそれは大したことではありません、var_dump()ですべてを印刷することでその中の何を表示したかったので、彼らは重要ではありません
Seyed Ali Roshan

なるほど、分かりました。私の注意を呼んだのは、公式ドキュメントでは、サンプルはvar_dump()も使用しているということです。だから私はそうする理由に興味がありました。何かが足りなかったかもしれません。php.net/manual/en/function.http-response-code.php
Tomas Gonzalez

10

出力バッファリングを使用していない場合は、本文の出力の前にこの行を追加します。

header("HTTP/1.1 200 OK");

メッセージ部分(「OK」)を適切なメッセージに、ステータスコードを適切なコード(404、501など)に置き換えます。


2
(OKを置き換えるために)送信するメッセージは何でもかまいませんか?
FMaz008

これでうまくいきました。PHP 5.3を使用してWebサイトのお問い合わせフォームを作成していました。そして、この解決策は私にとってうまくいきました。これは、応答テキストと、AJAX要求の失敗関数のこのHTTPコードを提供します。私が欲しかったのはそれだけです。
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

問題は、Status:404 Not Foundヘッダーを送信することが原因です。それを上書きする必要があります。これも機能します:

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

header( "HTTP / 1.1 200 OK"); http_response_code(201); header( "Status:200 All rosy"); //作業
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

次の2つの異なる環境を介して、http_response_codeから異なる戻り値を取得できます。

  1. Webサーバー環境
  2. CLI環境

Webサーバー環境で、応答コードを提供した場合、または応答コードを提供しなかった場合は、以前の応答コードを返し、現在の値を出力します。デフォルト値は200(OK)です。

CLI環境では、応答コードを指定した場合はtrueが返され、response_codeを指定しなかった場合はfalseが返されます。

Response_codeの戻り値のWebサーバー環境の例:

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

Response_codeの戻り値のCLI環境の例:

var_dump(http_response_code()); // bool(false)
var_dump(http_response_code(501)); // bool(true)
var_dump(http_response_code()); // int(501)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.