PHP - WEB - 8. HTTPレスポンスの詳細
それではHTTPレスポンスの詳細について学習していきましょう。HTTPレスポンスもHTTPリクエストと同様に3つのパートで構成されています。

またヘッダフィールドとボディパートの間には空行によって分割されています。ここではGoogle Chromeに付属するデベロッパーツールを使って、先ほどの一覧を表示するプログラム( users.php )の返却するHTTPレスポンスについて確認していきましょう。
まずはGoogle Chromeを起動してデベロッパーツール(Networkタブ)を開きます。次にビルトインWebサーバを起動した状態でWebブラウザから次のURLにアクセスします。
http://localhost:8000/users.phpそうするとデベロッパーツール上でHTTPの通信データのキャプチャーを取得できます。

表示されている users.php をクリックして詳細を確認してみましょう。「Headers」タブに表示されている結果の中に「Response Headers」というセクションがあるので「view source」をクリックしてみましょう

レスポンスのヘッダフィールド(ステータスライン含む)が確認できるので表示内容をコピーしてテキストエディタに貼り付けてみましょう。
HTTP/1.1 200 OK
Host: localhost:8000
Date: Mon, 17 Aug 2020 10:33:02 GMT
Connection: close
X-Powered-By: PHP/7.3.11
Content-type: text/html; charset=UTF-8ここまでがHTTPレスポンスのヘッダフィールド(ステータスライン含む)です。次にレスポンスのボディパートは、「Headers」タブの2つとなりにある「Response」タブで確認できます。

「Response」タブに表示されている内容をコピーして、さきほどのレスポンスのヘッダフィールドに空行を挟んで追加してみましょう。
HTTP/1.1 200 OK
Host: localhost:8000
Date: Mon, 17 Aug 2020 10:33:02 GMT
Connection: close
X-Powered-By: PHP/7.3.11
Content-type: text/html; charset=UTF-8
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>PHP Sample</title>
</head>
<body>
  <h3>Users</h3>
  <hr>
  <table border="1">
    <tr>
      <th>NO</th>
      <th>NAME</th>
      <th>AGE</th>
    </tr>
      <tr>
      <td>1</td>
      <td>Andy</td>
      <td>20</td>
    </tr>
      <tr>
      <td>2</td>
      <td>Betty</td>
      <td>22</td>
    </tr>
      <tr>
      <td>3</td>
      <td>Carol</td>
      <td>19</td>
    </tr>
    </table>
</body>
</html>以上がWebサーバからのHTTPレスポンスです。Webブラウザはこのような通信データをWebサーバから受け取っているのです。
それではHTTPレスポンスの詳細について見ていきましょう。HTTPレスポンスの先頭行はステータスラインと呼びます。このステータスラインは以下の形式に従います。
HTTPバージョン ステータスコード フレーズ さきほどのHTTPレスポンスの場合は次のようになっています。
HTTP/1.1 200 OKこの場合、HTTPバージョンは 1.1 、ステータスコードは 200 、フレーズは OK と読み取ることができます。またここで登場するステータスコードおよびフレーズにはいくつかの種類があります。代表的なものを以下に示します。
- 200:OK
- 201:Created
- 302:Found
- 403:Forbidden
- 404:Not Found
- 500:Internal Server Error
- 503:Service Unavailable
HTTPのステータスコードは正常な通信が行えた場合 200 など 200 番台の数値を返します。また通信時にエラーが発生した場合は 404 や 500 といった数値を返します。 400 番台のエラーはクライアントサイド(Webブラウザ)のエラー、 500 番台のエラーはサーバサイドのエラーを意味します。たとえば 404 :Not FoundというステータスコードはWebブラウザがアクセスしたURLに誤りがあることを意味します。これはクライアントサイドのエラーです。一方の 503 :Service Unavailable というステータスコードは、一時的にサーバの負荷が高まっているせいで応答できないことを意味します。これはサーバサイドのエラーです。
300番台のステータスコードはリダイレクト(他のページへの移動)を意味します。これについては次の章で取り上げます。
次にヘッダフィールドが続きます。
Host: localhost:8000
Date: Mon, 17 Aug 2020 10:33:02 GMT
Connection: close
X-Powered-By: PHP/7.3.11
Content-type: text/html; charset=UTF-8Host ヘッダや Date ヘッダなど様々なヘッダフィールドが存在するのがわかります。ここで特に重要なのが Content-type ヘッダです。
Content-type: text/html; charset=UTF-8Content-type はレスポンスのボディパートに含まれるデータの形式を意味します。ここでは text/html; と指定していることからボディパートにはHTMLコンテンツが含まれていることを指示しています。また charset=UTF-8 という記述からボディパートのHTMLコンテンツはエンコーディングが UTF-8 であることを指示しています Content-type に指定可能な値の一部を以下に示します。
- text/html
- HTMLテキスト
 
- text/css
- CSSテキスト
 
- text/plain
- プレーンテキスト
 
- image/jpeg
- JPEG画像
 
- image/png
- PNG画像
 
HTTPレスポンスを受け取ったWebブラウザは、この Content-type に指定されている内容をもとにボディパートを解析します。たとえば Content-type: text/html; charset=UTF-8 と指定されている場合、Webブラウザはボディパートに含まれているコンテンツをHTMLとして画面に描画します。
さいごにレスポンスのボディパートについて確認しておきましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>PHP Sample</title>
</head>
<body>
  <h3>Users</h3>
  <hr>
  <table border="1">
    <tr>
      <th>NO</th>
      <th>NAME</th>
      <th>AGE</th>
    </tr>
      <tr>
      <td>1</td>
      <td>Andy</td>
      <td>20</td>
    </tr>
      <tr>
      <td>2</td>
      <td>Betty</td>
      <td>22</td>
    </tr>
      <tr>
      <td>3</td>
      <td>Carol</td>
      <td>19</td>
    </tr>
    </table>
</body>
</html>ここにはPHPで生成したHTMLコンテンツが含まれているのがわかります。ヘッダフィールドにある Content-type ヘッダはこのボディパートに含まれる内容がHTMLであることを意味します。
Content-typeの変更
ここではもう一つプログラム( users.php )を修正して、 Content-type ヘッダの挙動について確認しておきましょう。
<?php
$handle = fopen("users.csv", "r");
$users = [];
while(($line = fgetcsv($handle)) !== false) {
  $users[] = $line;
}
fclose($handle);
header("Content-type: text/plain");
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>PHP Sample</title>
</head>
<body>
  <h3>Users</h3>
  <hr>
  <table border="1">
    <tr>
      <th>NO</th>
      <th>NAME</th>
      <th>AGE</th>
    </tr>
  <?php
    for ($i = 0; $i < count($users); $i++) {
  ?>
    <tr>
      <td><?php echo $users[$i][0] ?></td>
      <td><?php echo $users[$i][1] ?></td>
      <td><?php echo $users[$i][2] ?></td>
    </tr>
  <?php
    }
  ?>
  </table>
</body>
</html>このプログラムは先頭のPHPプログラムに header("Content-Type: text/plain"); を追加しています。 header 関数はレスポンスのヘッダフィールドを操作するための関数で、引数に指定した内容(この場合、 "Content-Type: text/plain" )をヘッダフィールドに追加します。
プログラムを修正したらビルトインWebサーバを起動し、Webブラウザ上でデベロッパーツールを起動して以下のURLを入力します。
http://localhost:8000/users.phpそうすると次のような実行結果が表示されるでしょう。

Webブラウザ上でHTMLコンテンツが描画されておらず、テキストデータとして出力されているのがわかります。デベロッパーツールからHTTPレスポンスを調べると次のような通信データになっていることがわかります。
HTTP/1.1 200 OK
Host: localhost:8000
Date: Mon, 17 Aug 2020 10:48:49 GMT
Connection: close
X-Powered-By: PHP/7.3.11
Content-type: text/plain;charset=UTF-8
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>PHP Sample</title>
</head>
<body>
  <h3>Users</h3>
  <hr>
  <table border="1">
    <tr>
      <th>NO</th>
      <th>NAME</th>
      <th>AGE</th>
    </tr>
      <tr>
      <td>1</td>
      <td>Andy</td>
      <td>20</td>
    </tr>
      <tr>
      <td>2</td>
      <td>Betty</td>
      <td>22</td>
    </tr>
      <tr>
      <td>3</td>
      <td>Carol</td>
      <td>19</td>
    </tr>
    </table>
</body>
</html>この通信データで注意してみてほしいのが Content-type: text/plain; の部分です。このように Content-type ヘッダの値が text/plain となっている場合、Google ChromeはボディパートのコンテンツをHTMLと解釈せずに、テキストデータとして解釈するようになっています。そのため画面にはHTMLコンテンツは描画されずに、テキストデータとして出力されることになります。
利用しているブラウザの種類やバージョンの違いによっては異なる表示となる場合もあります。
まとめ
- レスポンスのステータスラインにはステータスコードを含む
- Content-Typeヘッダはボディパートに含むデータのコンテンツの形式を示す
- レスポンスのボディパートにHTMLなどのコンテンツを格納する