web-dev-qa-db-ja.com

PHP:HTTPレスポンスコードを送信するにはどうすればいいですか?

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

どうすればPHPでこれを行うことができますか?

214
Paulo Coghi

私はちょうどこの質問を見つけ、それはもっと包括的な答えが必要だと思いました:

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 によると、理由句は次のようになります。任意のカスタム文字列(これは標準に準拠しています)が、クライアントの互換性のためにIにランダムな文字列を入れることを推奨しません

注:php_sapi_name() にはPHP 4.0.1が必要です

ヘッダ関数の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以下の互換性を必要としていたが "new" 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;
    }
}
407
dualed

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

  1. substr($sapi_type, 0, 3) == 'cgi'を使うことは速いCGIを検出するためには不向きです。 PHP-FPM FastCGI Process Managerを使用している場合、php_sapi_name()はcgiではなくfpmを返します。

  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. http_response_code()を呼び出して予期しない動作が発生する場合、少なくとも2つのケースがあります。

    • PHPが理解できないHTTPレスポンスコードに遭遇すると、PHPはそのコードを同じグループからのものと置き換えます。たとえば、 "521 Webサーバーがダウンしています"は "500 Internal Server Error"に置き換えられます。他のグループ2xx、3xx、4xxからの他の多くの珍しい応答コードはこのように処理されます。
    • Php-fpmとnginxのhttp_response_code()関数を持つサーバーでは、期待どおりにコードを変更することができますが、メッセージを変更することはできません。これは、例えば奇妙な "404 OK"ヘッダになるかもしれません。この問題はPHP Webサイトのユーザーコメントでも言及されています http://www.php.net/manual/en/function.http-response-code.php#11242

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

このバグを簡単にテストすることができます:

http_response_code(521);

たとえば、カスタムクライアントアプリケーションがサーバーを呼び出し、追加のHTTPコードを予期している場合、サーバーは "500 Internal Server Error" 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を処理しません。現在のプロトコルを検出する必要があります。

テストやコメントは大歓迎です。

34
Grigore Madalin

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

12

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

header("HTTP/1.1 200 OK");

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

7
sparkey0

環境をロードするときに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");
6
jaggedsoft

header 関数を使います。最初のパラメータのセクションに例があります。

5
Quentin
header("HTTP/1.1 200 OK");
http_response_code(201);

http_response_code(200)。テストアラート404のため動作しません https://developers.google.com/speed/pagespeed/insights/

1
alpc

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

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

Webサーバー環境では、応答コードを指定した場合、または応答コードを指定しなかった場合は前の応答コードを返します。その場合、現在の値が表示されます。デフォルト値は200(OK)です。

CLI環境では、応答コードを指定した場合はtrueが返され、応答コードを指定しなかった場合は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)
0
GaziAnis