PHP - WEB - 9. HTTPレスポンスの詳細

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

  • ステータスライン
  • ヘッダフィールド
  • ボディパート

ここではGoogle Chromeに付属するデベロッパーツールを使って、先ほどの一覧を表示するプログラム( users.php )の返却するHTTPレスポンスについて確認していきましょう。

まずはGoogle Chromeを起動してデベロッパーツール(Networkタブ)を開きます。次にビルトインWebサーバを起動した状態でWebブラウザから次のURLにアクセスします。

https://〜.vfs.cloud9.ap-northeast-1.amazonaws.com/users.php

そうするとデベロッパーツール上でHTTPの通信データのキャプチャーを取得できます。

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

「General」セクションには、HTTPレスポンスの1つ目のパートであるステータスラインに含まれるステータスコードが表示されています。

Status Code: 200

このステータスコードの 200 には正常な通信ができたという意味があります。

次に「Response Headers」の内容をコピーしてテキストエディタに貼り付けてみましょう。

content-type: text/html; charset=UTF-8
date: Thu, 25 Nov 2021 08:23:15 GMT
host: c6327f0f708344ba914531f340671547.vfs.cloud9.ap-northeast-1.amazonaws.com
set-cookie: AWSALB=BrcbWVnPe9ETqo53d1d6iVD6cqcUyIUFJDPcdYGtwWUgkmexV6Gmt8O3/Vm3/W4n3vGKFchoO0/gNwd1aGNaPd7T2avue5N8YBTcLQIYUf+rLRT/9umwi2GhGpBB; Expires=Thu, 02 Dec 2021 08:23:15 GMT; Path=/
set-cookie: AWSALBCORS=BrcbWVnPe9ETqo53d1d6iVD6cqcUyIUFJDPcdYGtwWUgkmexV6Gmt8O3/Vm3/W4n3vGKFchoO0/gNwd1aGNaPd7T2avue5N8YBTcLQIYUf+rLRT/9umwi2GhGpBB; Expires=Thu, 02 Dec 2021 08:23:15 GMT; Path=/; SameSite=None; Secure
x-powered-by: PHP/7.2.24

ここまでがHTTPレスポンスの2つ目のパートであるヘッダフィールドに格納されているデータです。普段このようなデータを目にすることはありませんが、Webサーバ(ここではビルトインWebサーバ)はこのようなデータを生成して、ブラウザに返却しているのです。

後ほど Content-Type ヘッダの仕組みについて解説します。その他のヘッダフィールドの解説については割愛します。

さいごにレスポンスの3つ目のパートであるボディパートに含まれるデータは「Headers」タブの2つとなりにある「Response」タブで確認できます。

「Response」タブに表示されている内容をコピーしてテキストエディタに貼り付けてみましょう。

<!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>

これがHTTPレスポンスのボディパートに含まれるデータです。PHPで echo 命令などを使って出力するデータはこのボディパートに格納されることになります。

以上がWebサーバからのHTTPレスポンスです。WebブラウザはHTTPレスポンス(ステータスライン、ヘッダフィールド、ボディパート)としてこのような通信データをWebサーバから受け取っているのです。

ステータスコード

HTTPレスポンスのステータスコードについて確認しておきましょう。HTTPにはここで登場した 200 以外にもいくつかのステータスコードが用意されています。代表的なものを以下に示します。

  • 200 :OK
  • 201 :Created
  • 302 :Found
  • 403 :Forbidden
  • 404 :Not Found
  • 500 :Internal Server Error
  • 503 :Service Unavailable

HTTPのステータスコードは正常な通信が行えた場合 200 など 200 番台の数値を返します。

また通信時にエラーが発生した場合は 404500 といった数値を返します。 400 番台のエラーはクライアントサイド(Webブラウザ)のエラー、 500 番台のエラーはサーバサイドのエラーを意味します。たとえば 404 :Not FoundというステータスコードはWebブラウザがアクセスしたURLに誤りがあることを意味します。これはクライアントサイドのエラーです。一方の 503 :Service Unavailable というステータスコードは、一時的にサーバの負荷が高まっているせいで応答できないことを意味します。これはサーバサイドのエラーです。

300 番台のステータスコードはリダイレクト(他のページへの移動)を意味します。これについては次の章で取り上げます。

content-type ヘッダ

さきほどのHTTPレスポンスのヘッダフィールドをもう一度見てみましょう。

content-type: text/html; charset=UTF-8
date: Thu, 25 Nov 2021 08:23:15 GMT
host: c6327f0f708344ba914531f340671547.vfs.cloud9.ap-northeast-1.amazonaws.com
set-cookie: AWSALB=BrcbWVnPe9ETqo53d1d6iVD6cqcUyIUFJDPcdYGtwWUgkmexV6Gmt8O3/Vm3/W4n3vGKFchoO0/gNwd1aGNaPd7T2avue5N8YBTcLQIYUf+rLRT/9umwi2GhGpBB; Expires=Thu, 02 Dec 2021 08:23:15 GMT; Path=/
set-cookie: AWSALBCORS=BrcbWVnPe9ETqo53d1d6iVD6cqcUyIUFJDPcdYGtwWUgkmexV6Gmt8O3/Vm3/W4n3vGKFchoO0/gNwd1aGNaPd7T2avue5N8YBTcLQIYUf+rLRT/9umwi2GhGpBB; Expires=Thu, 02 Dec 2021 08:23:15 GMT; Path=/; SameSite=None; Secure
x-powered-by: PHP/7.2.24

host ヘッダや date ヘッダなど様々なヘッダフィールドが存在するのがわかります。これらのヘッダフィールドの中で、特に重要なのが content-type ヘッダです。

content-type: text/html; charset=UTF-8

content-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として画面に描画します。一方で content-type: text/plain; charset=UTF-8 と指定されている場合、Webブラウザはボディパートに含まれているコンテンツをテキストコンテンツとして画面にそのまま出力します。

実際には content-type ヘッダの値に基づく挙動はWebブラウザの実装に依存します。

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を入力します。

https://〜.vfs.cloud9.ap-northeast-1.amazonaws.com/users.php

そうすると次のような実行結果が表示されるでしょう。

Webブラウザ上でHTMLコンテンツが描画されておらず、テキストデータとして出力されているのがわかります。デベロッパーツールからHTTPレスポンスを調べると次のような通信データになっていることがわかります。

この通信データで注意してみてほしいのが content-type: text/plain; の部分です。このように content-type ヘッダの値が text/plain となっている場合、Google ChromeはボディパートのコンテンツをHTMLと解釈せずに、テキストデータとして解釈するようになっています。そのため画面にはHTMLコンテンツは描画されずに、テキストデータとして出力されることになります。

利用しているブラウザの種類やバージョンの違いによっては異なる表示となる場合もあります。

まとめ

  • レスポンスのステータスラインにはステータスコードを含む
  • content-type ヘッダはボディパートに含むデータのコンテンツの形式を示す
  • レスポンスのボディパートにHTMLなどのコンテンツを格納する