PHP入門 リクエスト情報 ヘッダー情報($_SERVER)

クライアントからサーバーに送信される情報は、クライアントの種類や対応する言語、リンク元のページなど、さまざまな情報が内部的に生成されて、サーバーに送信されています。このような不可視の情報のことをヘッダー情報(リクエストヘッダー情報)と言います。

ヘッダー情報の種類

chromeブラウザのデベロッパーツールで見たヘッダー情報

chromeブラウザのデベロッパーツール

HTTP通信で利用可能な主なヘッダー

種類ヘッダー名概要
一般Cache-Controlキャッシュルールを規定する
Connectionレスポンス後に接続を維持するか
Dateコンテンツを生成した日時
Transfer-Encodingコンテンツの転送エンコーディング方式
リクエストAcceptクライアントがサポートしているコンテンツの種類(優先順)
Accept-Languageクライアントが対応している言語(優先順)
Authorization認証情報
Cookieクライアントに保存されたクッキーを送信
Host要求先のホスト名
If-Modified-Since指定された日時以降にコンテンツが更新されている場合にのみ、サーバーはデータを送信
Proxy-Authorizationプロキシサーバー用の認証情報
Range要求するリソースの範囲
Refererリンク元のURl
User-Agentクライアントの種類
レスポンスETagリソースを一意に特定するためのキー情報(コンテンツが更新されていないかどうかを特定する場合などに使用)
Expiresコンテンツの有効期限
Last-Modifiedコンテンツの最終更新年月日
Locationクライアントに新しいURIに移動するように促す
Serverサーバーの種類
Set-Cookieクライアントにクッキーを送信
WWW-Authenticateクライアントに認証を要求
エンティティContent-Encodingコンテンツのエンコーディング方式
Content-Lengthコンテンツのサイズ
Content-Typeコンテンツの種類

ヘッダー情報の利用方法

ヘッダーには多数の情報が含まれています。これらの情報をさまざまな目的に利用できます。たとえば、User-Agentヘッダーを利用すれば、サイトにアクセスしてきたクライアントの種類がわかります。これをアクセスログとして記憶しておけば、自分のページにアクセスしているユーザーの傾向を把握したり、検索エンジンのクローラーの巡回頻度を知ることができます。あるいは、デスクトップブラウザか携帯端末向けのブラウザを区別してコンテンツ形式を選択的に出力する、などといったことも可能です。Refererヘッダーを利用することで、自分のサイトにどのようなページからリンクが張られているのか、自分のサイト内でユーザーがどのようにページ間を移動しているのか把握できます。アクセス数だけではなく、このような傾向もあわせて分析することで、コンテンツそのおのやサイトの構造を改善する手がかりになります。

また、Accept-Languageヘッダーはクライアントの対応言語を表します。この情報をもとにすれば日本語環境のユーザーには日本語、英語環境のユーザーには英語を表示するというように、クライアントの言語に応じたページを構築することもできます。

リクエストヘッダーを取得する

リクエストヘッダーを取得するには、スーパーグローバル変数$_SERVERを参照します。ただし、$_SERVERはリクエストヘッダーの他に、サーバー変数(サーバーが提供する環境情報)を含みます。$_SERVERでは、ヘッダー情報とサーバー変数とを識別するために、生のヘッダー名を次の規則で整形したものを格納しています。

  • ハイフン(-)はアンダースコア(_)に変換
  • 接頭辞として「HTTP_」を付加

したがって、User-Agentヘッダーを取得するには、$_SERVER[‘HTTP_USER_AGENT’]のように記述する必要があります。(ヘッダー名はすべて大文字で記述します)str_starts_with関数で「HTTP_」で始まるキー名だけを取り出すことで、リクエストヘッダーの情報だけを出力しています。

主なサーバー変数

変数名概要値(例)
DOCUMENT_ROOTドキュメントルートC:/xampp/htdocs
GATEWAY_INTERFACECGIのリビジョンCGI/1.1
HTTPSHTTPSプロトコルを利用しているか
PATH_INFO実行ファイル名とクエリ文字列の間のパス情報/tmp
PATH_TRANSLATED実行中のスクリプトのファイルシステム上のパスC:\xampp\htdocs\tmp
PHP_SELF実行中のスクリプト/tmp
PHP_AUTH_DIGESTHTTPダイジェスト認証時のAuthorizationヘッダーの内容
PHP_AUTH_USERHTTP認証時のユーザー名admin_usr
PHP_AUTH_PWHTTP認証時のパスワードadmin_pass
QUERY_STRINGクエリ情報category=PHP
REMOTE_ADDRクライアントのIPアドレス::1
REMOTE_HOSTクライアントのホスト名localhost
REMOTE_PORTクライアントのポート番号49877
REQUEST_METHODHTTPメソッドGET
REQUEST_TIMEリクエスト開始時のタイムスタンプ1609140540
REQUEST_URI指定されたURIC:/xampp/htdocs
SCRIPT_FILENAME実行中のスクリプト(絶対パス)C:/xampp/htdocs/sample.php
SCRIPT_NAME実行中のスクリプト/htdocs/sample.php
SERVER_ADDRサーバーのIPアドレス::1
SERVER_ADMINサーバー管理者のメールアドレスwebmaster@example.com
SERVER_NAMEサーバー名localhost
SERVER_PORTサーバーのポート80
SERVER_PROTOCOLプロトコル名、リビジョンHTTP/1.1
SERVER_SIGNATUREサーバーのバージョン<address>Apache/2.4.46</address>
SERVER_SOFTWAREサーバーのソフトウェアApache/2.4.46
<?php require_once './Encode.php';?>
<!DOCTYPE html>
<head>
<meta charset="UTF-8" />
<title>PHPサンプル</title>
<style>
    th,td{
        border:solid 1px;
        text-align: left;
        }
</style>
</head>
<body>
    <table>
        <?php
        //$_SERVERのキー/値を順に取得
        foreach($_SERVER as $key => $value){
            //キー($key)が「HTTP_」ではじまる場合のみ、その値を出力
            if(str_starts_with($key, 'HTTP_')){
        ?>
        <tr>
            <th><?=e($key)?></th>
            <th><?=e($value)?></th>
        <?php
        }
    }   
        ?>
    </table>
</body>
</html>
実行結果
リクエスト時に送信されたヘッダー情報を一覧表示

レスポンスヘッダーを設定する

PHPからスクリプトからレスポンスヘッダーを操作することも可能です。

Locationヘッダーでリダイレクトする

例:Locationヘッダーを設定することで、指定したページにリダイレクトする

<?php
header('Location: http://localhost/sample2.php');

構文:header関数

header(string $header [, bool $replace = true [, int $response_code]]): void
$headerヘッダー文字列(「ヘッダー名:値」の形式)
$replace同名のヘッダーが出力済みである場合に置き換えるか
$response_codeHTTP応答ステータス

レスポンスヘッダーを設定するのは、header関数の役割です。また、Locationヘッダーは、リダイレクト先のURI(URL)を表すためのレスポンスヘッダーです。クライアントのブラウザではLocationヘッダーを受け取ると、指定のアドレスへ自動的にリクエストを発行します。リダイレクトは1つのリクエスト処理に見えますが、HTTPの観点では、2回のリクエストが自動的に行われています。

リダイレクト先を表すホスト名やフォルダのパスは、実際にはスーパーグローバル変数$_SERVERを使って取得する方法

redirect.php

header('Location: http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/req_headers.php');

$_SERVER[‘HTTP_HOST’]はサーバーのホスト名、$_SERVER[’PHP_SELF’]は実行中のスクリプトのパスを表します。dirnameはパスから親フォルダのパスを取り出すための関数です。

header関数でLocationヘッダーを発行した場合、既定でHTTPステータス302(Found/Moved Temporarily)を出力します。ただし、これは厳密には正しいステータスコードではありません。HTTPの規約では、HTTPステータス302はリダイレクト時にHTTPメソッドを変更してはならないことになっているからです。つまりは、HTTP POSTメソッドでのリクエストは、そのままHTTP POSTでリダイレクトしなければなりません。歴史的な経緯から間違った用法がまかり通りっているため、このままでも動作に問題がありませんが、より正しくは、header関数の引数$codeに303(See Other)を指定したほうがよいでしょう。ちなみに、古いアドレスから新しいアドレスにユーザーを誘導するような用途では、301を利用します。既定の302はMovedTemporarily(一時的なアドレスの移動)を意味するため、検索エンジンのクローラーはリダイレクト先のアドレスをあくまで一時的なものとして記録しません。しかし、301は恒久的な移動を意味するため、リダイレクト先のアドレスを新しいアドレスとして記録します。

キャッシュ処理を無効にする

Expires、Last-Modified、Cache-Controlなどのレスポンスヘッダーを指定することで、ブラウザやプロキシサーバーでのキャッシュ処理を強制的に無効にできます。

<?php
//ページの有効期限を過去の日付に設定
header('Expires: Sun, 15 Jan 1970 00:00:00 GMT');
//最終更新日を常に最新
header('Last-Modified: '. gmdate('D, d M Y H:i:s').'GMT');
//キャッシュを無効に設定
header('Cache-Control: no-store, no-cache, must-revalidate');

強制的に認証ダイアログを表示させる

HTTPステータスとして「401 Unauthorized」(未認証)を発行することで、ブラウザで強制的に認証ダイアログを表示できます。➊は強制的に認証ダイアログを表示させるコード。キャンセルされた場合は❷以降の処理を実行し、ユーザー名/パスワードが入力された場合は、再度、phpが読み込まれます。

<?php
//認証ユーザー名が送信されているか判定
if(!isset($_SERVER['PHP_AUTH_USER'])){
    header('HTTP/1.1 401 Unauthorized');                  //➊
    header('WWW-Authenticate: Basic realm="SelfPHP"');    //➊
    print 'この画面へのアクセスは認められませんでした。';     //➋
    die();
//認証ユーザー名が送信されている場合はユーザー名/パスワードを確認
}else{
    //認証ユーザー名が送信されている場合はユーザー名/パスワードを確認
    if($_SERVER['PHP_AUTH_USER'] === 'admin_usr' && $_SERVER['PHP_AUTH_PW'] === 'admin_pass'){
        print '正しく認証が行われました。';

    }else{
        print 'ユーザー名、またはパスワードが間違っています。';
    }
}
実行結果
実行結果

さまざまな種類のファイルを生成したい

クライアントは受信したコンテンツをどのように処理するかは、Content-Typeヘッダー(コンテンツタイプ)によって決定します。PHPは既定で「text/html」というコンテンツタイプを送信します。HTML以外のデータを送信する場合は、スクリプト側で明示的にContent-Typeヘッダーを生成する必要があります。

header('Content-Type: application/pdf');  //PDF文書を出力

主なコンテンツタイプ

コンテンツタイプファイルの種類拡張子
application/octet-stream任意のバイナリデータ
application/pdfPDF文書.pdf
image/gifGIF画像.gif
image/jpegJPEG画像.jpeg、.jpg
image/pngPNG画像.png
text/cssCSSスタイルシート.css
text/htmlHTML文書.htm、.html
text/plain普通のテキスト.txt
text/xmlXML文書.xml
application/jsonJSONデータ.json
audio/mpeg音声データ.mp3

Content-Typeヘッダーを利用することで、ファイルを強制的にダウンロードさせるようなスクリプトも記述できます。

<?php
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename = "flower.jpg"');
print file_get_contents('./doc/flower.jpg');