PHPでリクエストヘッダーを読み取る方法


271

PHPでヘッダーを読み取るにはどうすればよいですか?

たとえば、カスタムヘッダー:X-Requested-With

回答:


345

IFすべてのヘッダーではなく単一のヘッダーのみが必要な場合、最も速い方法は次のとおりです。

<?php
// Replace XXXXXX_XXXX with the name of the header you need in UPPERCASE (and with '-' replaced by '_')
$headerStringValue = $_SERVER['HTTP_XXXXXX_XXXX'];


ELSE IF:PHPをApacheモジュールとして実行するか、PHP 5.4以降ではFastCGI(単純な方法)を使用します。

apache_request_headers()

<?php
$headers = apache_request_headers();

foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}


ELSE:それ以外の場合は、(ユーザーランド実装)を使用できます。

<?php
function getRequestHeaders() {
    $headers = array();
    foreach($_SERVER as $key => $value) {
        if (substr($key, 0, 5) <> 'HTTP_') {
            continue;
        }
        $header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
        $headers[$header] = $value;
    }
    return $headers;
}

$headers = getRequestHeaders();

foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}


関連項目
getallheaders() -(PHP> = 5.4)クロスプラットフォーム版apache_request_headers() apache_response_headers()のエイリアス-すべてのHTTP応答ヘッダーをフェッチします。
headers_list() -送信するヘッダーのリストを取得します。


3
これはApacheサーバーを使用しているときだけだと思います... OPにそれを知らせる必要があるかもしれません:)
alex

12
アマチュアの82%は気にしません。私はプロのインスタレーションを気にします。mod_phpでトラフィックの多いサイトを実行しようとするのは、適切な心構えのある人ではありません。
vartec 2011年

11
@Jaccoはい、そして私はそれが反対投票の完全な理由になると思います。常に、最良の回答には賛成票を投じ、悪い答えには反対票を投じるべきです。これは歴史的な解決策のサイトではありません:-)
Thomas Jensen '29

3
@ThomasJensenただし、一部のヘッダーが他のヘッダーまたはすべてのヘッダーに含まれている可能性があり、特に「HTTP_X_REQUESTED_WITH」には含まれていない可能性があることを考慮してください。回答者は完全に正解であり、JaccoはそれがApacheでのみ機能することを明言しています。いくつかのシナリオでそれが最良/最もパフォーマンスの高いソリューションではないことは、IMOを下げる理由にはなりません。
Sebastian Hoffmann

1
@Paranaix A:どういう意味かわかりません。答えの範囲を批判していません。あなたの推論は、具体的な質問に答えることによって私の答えを始めた理由であり、その後、より一般的な知識と詳細情報へのリンクで詳しく説明しました。B:apache_request_headers()の使用を奨励すべきではないと私はまだ思いません。この質問を見つけた初心者は、より良い機能が存在する場合は残念なIMOであるこの質問を使い始めます。
Thomas Jensen

371
$_SERVER['HTTP_X_REQUESTED_WITH']

RFC3875、4.1.18

HTTP_使用されているプロトコルがHTTPの場合、名前が先頭のメタ変数には、クライアント要求ヘッダーフィールドから読み取られた値が含まれます。HTTPヘッダフィールド名は大文字に変換され、すべての出現は、た-と置き換え_としているHTTP_メタ変数名を与えるために付加します。


6
サーバーがすべてのヘッダーを$_SERVER変数に入れることを確実に期待できますか?php.net/manual/en/reserved.variables.server.phpにあるPHPのドキュメントは、そこにあると確信できるものについては回避的です。
Mark Amery 2013年

4
これは(常に)、特にPHP-fpm(またはcgi)では機能しません。このヘッダーは、PHP内から常に利用できるとは限りません。
Glenn Plas 2013年

このソリューションを使用すると、リクエストヘッダーの一部しか表示されず、この場合、必要なヘッダーが表示されません。Chromeはcache-controlヘッダーを送信していますが、には表示されません$_SERVERHTTP_「HTTP_ACCEPT」、「HTTP_UPGRADE_INSECURE_REQUESTS」、「HTTP_USER_AGENT」など、先頭にが付いたいくつかのヘッダーが表示されます(他にもいくつかあります)。しかし、「キャッシュ制御」には何も、「プラグマ」にも何もありません。これは、大文字と小文字またはHTTP_プレフィックスに関係あり ません。何か不足していますか?
エヴァンデラクルーズ

@EvandelaCruz:leserged.online.fr/phpinfo.php私はここでそれを参照してください_SERVER["HTTP_CACHE_CONTROL"] max-age=0
Quassnoi

うーん、ありがとう...これは私のwamp devサーバー上にあり、PHPはApacheモジュールとして実行されていると思いますが、よくわかりません。FPMを使用して製品ボックスを確認し、なぜここに表示されないのか理解できるかどうか確認してみましょう...
Evan de la Cruz

48

すべて大文字のダッシュとダッシュ(-)が下線(_)に置き換えられた$_SERVERグローバル変数ですべてのHTTPヘッダーを検索する必要がありますHTTP_

たとえば、次の場所にありますX-Requested-With

$_SERVER['HTTP_X_REQUESTED_WITH']

$_SERVER変数から連想配列を作成すると便利な場合があります。これはいくつかのスタイルで実行できますが、キャメルケースキーを出力する関数を次に示します。

$headers = array();
foreach ($_SERVER as $key => $value) {
    if (strpos($key, 'HTTP_') === 0) {
        $headers[str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))))] = $value;
    }
}

次に$headers['XRequestedWith']、目的のヘッダーを取得するために使用します。

PHPマニュアル$_SERVERhttp : //php.net/manual/en/reserved.variables.server.php


3
私の意見では、最良の答えは、トマスの説明とクアスノイの最終結果です。連想配列は通常、必要なものではなく、parseRequestHeaders()関数を読み取って簡単なソリューションを作成するのは簡単ではありません。このような連想配列が必要な場合は、apache関数のIMOが最適なオプションです。これは、CamelCaseのマングルバージョンではなく、受け取ったヘッダーを正確に返すためです。(また、PHP 5.4以降は、Apacheのみではなくなりました。)
Brilliand

この2年と11か月早く答えるとしたら、この答えには200以上の賛成票があります。
DividedByZero 2014年

apache_request_headers()またはgetallheaders()私がテストしたときにヘッダー名を大文字にしていないようです。彼らは私がクライアント側から渡す通りに戻ってきています。では、なぜこのような置換関数でヘッダー名を大文字にするのでしょうか。
rineez

22

PHP 5.4.0以降getallheadersでは、すべてのリクエストヘッダーを連想配列として返す関数を使用できます。

var_dump(getallheaders());

// array(8) {
//   ["Accept"]=>
//   string(63) "text/html[...]"
//   ["Accept-Charset"]=>
//   string(31) "ISSO-8859-1[...]"
//   ["Accept-Encoding"]=>
//   string(17) "gzip,deflate,sdch"
//   ["Accept-Language"]=>
//   string(14) "en-US,en;q=0.8"
//   ["Cache-Control"]=>
//   string(9) "max-age=0"
//   ["Connection"]=>
//   string(10) "keep-alive"
//   ["Host"]=>
//   string(9) "localhost"
//   ["User-Agent"]=>
//   string(108) "Mozilla/5.0 (Windows NT 6.1; WOW64) [...]"
// }

以前、この関数は、PHPがApache / NSAPIモジュールとして実行されている場合にのみ機能しました。


20
PHP-FPM 5.5とNGINXで使用しています。getallheaders()は存在しません。
CMCDragonkai 2013

FCMの@CMCDragonkaiでは、ヘッダー情報をどのように取得しましたか?
Ajit Singh

5

strtolowerRFC2616(HTTP / 1.1)は、提案されたソリューションのいくつかに欠けているため、大文字と小文字を区別しないエンティティとしてヘッダーフィールドを定義しています。価値のある部分だけでなく、全体。

したがって、HTTP_エントリの解析のみのような提案は間違っています。

次のようにするとよいでしょう。

if (!function_exists('getallheaders')) {
    foreach ($_SERVER as $name => $value) {
        /* RFC2616 (HTTP/1.1) defines header fields as case-insensitive entities. */
        if (strtolower(substr($name, 0, 5)) == 'http_') {
            $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
        }
    }
    $this->request_headers = $headers;
} else {
    $this->request_headers = getallheaders();
}

以前の提案との微妙な違いに注意してください。この関数は、php-fpm(+ nginx)でも機能します。


1
RFC 2616では、フィールド値は大文字と小文字を区別しないと正確にどこに記述されていますか?「HTTP-dateは大文字と小文字が区別される」とDateヘッダーに入ると「パラメータ値[セミコロンの後のContent-Typeのテキスト]は大文字と小文字が区別される場合とされない場合がある」と露骨に述べています。したがって、大文字と小文字を区別する値を持つヘッダーが少なくとも2つあることを考えると、それは間違っているようです。
Joker_vD

HTTP header fields, which include general-header (section 4.5), request-header (section 5.3), response-header (section 6.2), and entity-header (section 7.1) fields, follow the same generic format as that given in Section 3.1 of RFC 822 [9]. Each header field consists of a name followed by a colon (":") and the field value. Field names are case-insensitive. だから私はあなたが間違っていると思います。
Glenn Plas

4
フィールドは大文字と小文字を区別しません。この段落ではフィールドについては何もありませんが、ドキュメントの他の部分では、大文字と小文字を区別するフィールド値について明示的に説明しています。
Joker_vD

1
なぜ下線をスペースに、次にスペースをダッシュ​​に置き換えるのですか?これだけではうまくいきません:$ headers [ucwords(strtolower(substr($ name、5)))]] = $ value; ?
テミルベク

5

forループを使用せずに値を取得するには、この関数にヘッダー名を渡します。ヘッダーが見つからない場合はnullを返します。

/**
 * @var string $headerName case insensitive header name
 *
 * @return string|null header value or null if not found
 */
function get_header($headerName)
{
    $headers = getallheaders();
    return isset($headerName) ? $headers[$headerName] : null;
}

注:これはApacheサーバーでのみ機能します。http//php.net/manual/en/function.getallheaders.phpを参照してください。

注:この関数はすべてのヘッダーを処理してメモリにロードしますが、forループよりもパフォーマンスが低下します。


関数はエラーを持って、交換してください$ pHeaderKeyをする$ headerKey
Tegos

4

物事を簡単にするために、ここでは必要なものだけを取得する方法を示します。

シンプル:

$headerValue = $_SERVER['HTTP_X_REQUESTED_WITH'];

または、一度に1つずつ取得する必要がある場合:

<?php
/**
 * @param $pHeaderKey
 * @return mixed
 */
function get_header( $pHeaderKey )
{
    // Expanded for clarity.
    $headerKey = str_replace('-', '_', $pHeaderKey);
    $headerKey = strtoupper($headerKey);
    $headerValue = NULL;
    // Uncomment the if when you do not want to throw an undefined index error.
    // I leave it out because I like my app to tell me when it can't find something I expect.
    //if ( array_key_exists($headerKey, $_SERVER) ) {
    $headerValue = $_SERVER[ $headerKey ];
    //}
    return $headerValue;
}
// X-Requested-With mainly used to identify Ajax requests. Most JavaScript frameworks
// send this header with value of XMLHttpRequest, so this will not always be present.
$header_x_requested_with = get_header( 'X-Requested-With' );

その他のヘッダーもスーパーグローバル配列$ _SERVERにあります。ヘッダーの取得方法については、http//php.net/manual/en/reserved.variables.server.phpを参照してください。


他の回答と比較すると、HTTP_$headerKey
先頭に追加さ

3

私はCodeIgniterを使用していて、それを取得するために以下のコードを使用しました。将来誰かのために役立つかもしれません。

$this->input->get_request_header('X-Requested-With');

そうだった。get_request_header()メソッドについては知っていましたが、ヘッダー名をそのまま使用できるかどうか、つまりハイフンをアンダースコアに変更する必要がないかどうかはわかりませんでした。
Valkay、

それが助けてうれしい。乾杯。
Rajesh

1

これが私のやり方です。$ header_nameが渡されない場合は、すべてのヘッダーを取得する必要があります。

<?php
function getHeaders($header_name=null)
{
    $keys=array_keys($_SERVER);

    if(is_null($header_name)) {
            $headers=preg_grep("/^HTTP_(.*)/si", $keys);
    } else {
            $header_name_safe=str_replace("-", "_", strtoupper(preg_quote($header_name)));
            $headers=preg_grep("/^HTTP_${header_name_safe}$/si", $keys);
    }

    foreach($headers as $header) {
            if(is_null($header_name)){
                    $headervals[substr($header, 5)]=$_SERVER[$header];
            } else {
                    return $_SERVER[$header];
            }
    }

    return $headervals;
}
print_r(getHeaders());
echo "\n\n".getHeaders("Accept-Language");
?>

他の回答で示されているほとんどの例よりもはるかに単純に見えます。これは、すべてのヘッダーを取得するときに要求されたメソッド(GET / POST / etc。)とURIも取得します。これは、ロギングでそれを使用しようとしている場合に役立ちます。

出力は次のとおりです。

Array ( [HOST] => 127.0.0.1 [USER_AGENT] => Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0 [ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 [ACCEPT_LANGUAGE] => en-US,en;q=0.5 [ACCEPT_ENCODING] => gzip, deflate [COOKIE] => PHPSESSID=MySessionCookieHere [CONNECTION] => keep-alive )

en-US,en;q=0.5

0

これを行う簡単な方法を次に示します。

// echo get_header('X-Requested-With');
function get_header($field) {
    $headers = headers_list();
    foreach ($headers as $header) {
        list($key, $value) = preg_split('/:\s*/', $header);
        if ($key == $field)
            return $value;
    }
}

送信されるヘッダーではありませんか?
CMCDragonkai 2013年

@CMCDragonkaiいいえ。「headers_list()はブラウザ/クライアントに送信されるヘッダーのリストを返します」-php.net/manual/en/function.headers-list.php
kehers

2
うん。そういう意味です。
CMCDragonkai 2013年

1
問題は、サーバーに送信されるヘッダーを要求することです。それらは要求ヘッダーです。
CMCDragonkai 2013年

1
「送信済み」、「送信」、「宛先」、「送信元」などの用語を使用する場合、ソースと宛先は、それらの用語が使用されるコンテキストに関連しています。この回答の例は、サーバーで実行されているPHPを示しています。また、OPの質問では、サーバー側のPHPも参照されました。したがって、@ CMCDragonkaiとMichaelLeanyは正しいです。これは悪い答えです。この場合の「送信済み」とは、「サーバーから送信されたHTTP応答ヘッダー」を意味します。kehersはクライアントの観点からコメントしていますが、彼の回答とOPの質問はどちらもサーバーの観点からです。
エヴァンデラクルーズ

0

この小さなPHPスニペットは役に立ちます。

<?php
foreach($_SERVER as $key => $value){
echo '$_SERVER["'.$key.'"] = '.$value."<br />";
}
?>

0
function getCustomHeaders()
{
    $headers = array();
    foreach($_SERVER as $key => $value)
    {
        if(preg_match("/^HTTP_X_/", $key))
            $headers[$key] = $value;
    }
    return $headers;
}

この関数を使用してカスタムヘッダーを取得します。ヘッダーが「HTTP_X_」から始まる場合は、配列にプッシュします:)


0

取得するのに必要なキーが1つだけの場合、たとえば"Host"アドレスが必要な場合は、

apache_request_headers()['Host']

ループを回避してインラインでエコー出力に配置できるようにするため


PHP 5.4以降。5.3では、この構文によりエラーが発生します。
Robin K

これはPHP 7.1でテストされています
Dickens AS

0

PHP 7:Null Coalesceオペレーター

//$http = 'SCRIPT_NAME';
$http = 'X_REQUESTED_WITH';
$http = strtoupper($http);
$header = $_SERVER['HTTP_'.$http] ?? $_SERVER[$http] ?? NULL;

if(is_null($header)){
    die($http. ' Not Found');
}
echo $header;

-1

これは、Apacheサーバーがある場合に機能します。

PHPコード:

$headers = apache_request_headers();

foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}

結果:

Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0
Host: www.example.com
Connection: Keep-Alive
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.