PHP - WEB - 5. HTTPリクエストの詳細(GETリクエスト)

引き続きHTTPリクエストについて学習していきましょう。さきほどログインプログラムを作成する過程でログイン画面である login.html ファイルと、ログイン画面からのリクエストを処理する login.php ファイルの2つを作成しました。ここでは2つのファイルの間で具体的にどのようなデータのやりとりが発生するのかを見ていくことにします。

HTTPリクエストのキャプチャー(GETリクエスト)

これから学習していくように HTTPリクエストは以下の3つのパートで構成されています。

  • リクエストライン
  • ヘッダフィールド
  • ボディパート

ここではWebブラウザとWebサーバ間の通信において、これら3つのパートにどのようなデータが含まれているのかを検証していきます。

HTTPのバージョン2(HTTP/2)からはリクエストラインに含まれる項目を「擬似ヘッダフィールド」と呼ぶようになりました。ここではHTTP/1.x系の呼び方であるリクエストライン・ヘッダフィールド・ボディパートという言葉を使って解説します。また必要に応じて「擬似ヘッダフィールド」という呼び方も使って補足するようにします。

通常、WebブラウザからWebサーバに送信されるデータ(HTTPリクエスト)はユーザの目には触れない仕組みになっています。そのため従来は、通信データのキャプチャーを取得するに専用のソフトウェアを用意する必要がありましたが、最近のWebブラウザには「開発者ツール」や「デベロッパーツール」といった機能が提供されており、それらを使えば簡単に通信データを確認できるようになっています。

Google Chromeの場合は「その他のツール」 => 「デベロッパーツール」にアクセスすることでデベロッパーツールを起動できます。

F12キーで起動することもできます。

ChromeのデベロッパーツールにはWebアプリケーションの開発に役に立つ様々な機能が提供されています。その中にはWebブラウザとWebサーバ間の通信データのキャプチャーをとる機能も含まれています。それでは実際に通信データのキャプチャーを取得してみましょう。

まずはデベロッパーツールのNetworkタブを選択します。

Networkタブを開いた状態でリンクやボタンをクリックすると、その際に発生したHTTPリクエスト(レスポンス)のキャプチャーを取得できます。

それではさきほどのログインプログラム( login.html )を使って通信データのキャプチャーの取得にチャレンジしてみましょう。ここでは以下のように GET リクエストを送信するものとします。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>PHP Sample</title>
</head>
<body>
    <h3>Login</h3>
    <hr>
    <form action="login.php" method="get">
        <input type="text" name="id">
        <input type="password" name="password">
        <input type="submit" value="login">
    </form>
</body>
</html>

また送信されたリクエストを処理するプログラム( login.php )は以下のとおりです。こちらも前回と変更はありません。

<?php
$id = $_GET["id"];
$password = $_GET["password"];
$message = "NG";
if ($id === "Andy" && $password === "secret") {
    $message = "OK";
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>PHP Sample</title>
</head>
<body>
  <h1>Login <?php echo $message; ?></h1>
</body>
</html>

まずは以下のURLを入力してログイン画面( login.html )にアクセスします。

https://〜.vfs.cloud9.ap-northeast-1.amazonaws.com/login.html

次にデベロッパーツールを開いてNetworkタブを選択します。もし不要な通信データのキャプチャーが表示されている場合は「Clear」ボタンをクリックすることで通信データのキャプチャーを削除できます。

それではデベロッパーツール(Networkタブ)を開いた状態で、IDとパスワードを入力して送信ボタンをクリックしてみましょう。そうするとデベロッパーツール上に通信データが1件表示されるでしょう。

データにはStatusやTypeといった情報も合わせて出力されています。次のこの通信データをクリックすると次のような画面が表示されるでしょう。

ここに表示されている情報がHTTPリクエストとHTTPレスポンスの通信データです。

まずはHTTPリクエストに注目して見ていきましょう。画面をスクロールすると「Request Headers」というセクションがあります。

ここに表示されている内容がHTTPリクエスト(厳密にはリクエストラインとヘッダフィールド)です。デベロッパーツールに表示されている内容をコピーしてテキストエディタに貼り付けると次のようになります。

:authority: c6327f0f708344ba914531f340671547.vfs.cloud9.ap-northeast-1.amazonaws.com
:method: GET
:path: /login.php?id=Andy&password=secret
:scheme: https
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
accept-encoding: gzip, deflate, br
accept-language: ja,en-US;q=0.9,en;q=0.8
cookie: __Host-previewc9corsvfs_9c0d5j7Z1PFSFxRo=9ck6M6IHHfbozVDiAEl36pzUcbrA5FKq; AWSALB=NMWsnAJiw807evDwhq8UiBUh7Qi0KnWgfyBX4GdloIqpcNAX69PrBaT/BOM+8Bs5aOoH3p0hMXpCp0XkUOi2SJThKzg5+ie//1Wcog9Jc6Lky/2rOvAyJ3Xw3e+t; AWSALBCORS=NMWsnAJiw807evDwhq8UiBUh7Qi0KnWgfyBX4GdloIqpcNAX69PrBaT/BOM+8Bs5aOoH3p0hMXpCp0XkUOi2SJThKzg5+ie//1Wcog9Jc6Lky/2rOvAyJ3Xw3e+t
referer: https://c6327f0f708344ba914531f340671547.vfs.cloud9.ap-northeast-1.amazonaws.com/login.html
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
sec-fetch-dest: document
sec-fetch-mode: navigate
sec-fetch-site: same-origin
sec-fetch-user: ?1
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36

表示されている内容はWebブラウザの種類やバージョンによって異なる可能性があります。

複雑なデータがたくさん出力されていますが、ここですべてを理解する必要はありません。まずはHTTPリクエストの全体像を確認するだけで十分です。

先頭の :authority、:method、:path、:scheme は HTTP/2では擬似ヘッダフィールドと呼ばれます。これらの多くはHTTPリクエストの1つ目のパートであるリクエストラインに含まれるデータと考えて良いでしょう。

:authority: c6327f0f708344ba914531f340671547.vfs.cloud9.ap-northeast-1.amazonaws.com
:method: GET
:path: /login.php?id=Andy&password=secret
:scheme: https

ここにはHTTPリクエストの主要な情報が含まれています。まず :authority とはURL https://〜/ の〜の部分を意味しており、:scheme は通信スキーム(ここでは https )を意味しています。同様に :path はURLのパスの部分を意味します。:method ではHTTPリクエストの送信方法が GET 形式のリクエストであることを意味しています。GETリクエストの場合は :path の値に画面から入力したパラメータが格納されている点に注意してください。

HTTPのバージョンによって表記がことなります。HTTP/1.x ではこのような情報は「リクエストライン(あるいはスタートライン)」などと呼ばれていました。HTTP/2 では「擬似ヘッダフィールド」などと呼ばれます。Cloud9 は HTTP/2の通信をサポートしているのでこのような通信データを確認できます。

そのあとの部分はヘッダフィールドと呼ばれます。

accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
accept-encoding: gzip, deflate, br
accept-language: ja,en-US;q=0.9,en;q=0.8
cookie: __Host-previewc9corsvfs_9c0d5j7Z1PFSFxRo=9ck6M6IHHfbozVDiAEl36pzUcbrA5FKq; AWSALB=NMWsnAJiw807evDwhq8UiBUh7Qi0KnWgfyBX4GdloIqpcNAX69PrBaT/BOM+8Bs5aOoH3p0hMXpCp0XkUOi2SJThKzg5+ie//1Wcog9Jc6Lky/2rOvAyJ3Xw3e+t; AWSALBCORS=NMWsnAJiw807evDwhq8UiBUh7Qi0KnWgfyBX4GdloIqpcNAX69PrBaT/BOM+8Bs5aOoH3p0hMXpCp0XkUOi2SJThKzg5+ie//1Wcog9Jc6Lky/2rOvAyJ3Xw3e+t
referer: https://c6327f0f708344ba914531f340671547.vfs.cloud9.ap-northeast-1.amazonaws.com/login.html
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
sec-fetch-dest: document
sec-fetch-mode: navigate
sec-fetch-site: same-origin
sec-fetch-user: ?1
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36

これがHTTPリクエストの2つ目のパートであるヘッダフィールドに含まれるデータです。

ヘッダフィールドは1行が一つの項目と値となっており、: で区切られているのがわかります。ここでは先頭からaccept ヘッダや accept-encoding ヘッダ、一番下の行には user-agent ヘッダを確認できます。これら一つひとつのヘッダ情報にはそれぞれに意味があり、Webサーバとの通信のやりとりに利用されています。

ここでは個々のヘッダフィールドの詳細な解説については割愛します。今すぐ必要な知識ではありませんので、Webアプリケーションの理解が深まってからあらためて学習していくと良いでしょう。

ここで理解しておきたいポイントは、ユーザが画面からテキストボックスに Andysecret と入力して login ボタンをクリックすると、ChromeのようなWebブラウザは、ここで紹介したような通信データを生成してWebサーバにデータを送っているという点です。このような送信データをHTTPリクエストと呼んでいます。

さいごにHTTPリクエストを構成する3つのパートについて確認しておきましょう。

  • リクエストライン
  • ヘッダフィールド
  • ボディパート

これまでの説明で、リクエストラインやヘッダフィールドに含まれるデータについての説明はありましたが、3つ目のパートであるボディパートについては説明ができていません。実はHTTPリクエストにおいて、GETリクエストを送信する場合は3つ目のパートであるボディパートは利用しない、という取り決めになっています。次に学習するPOSTリクエストではこのボディパートを利用してデータを送信することになります。

まとめ

  • ブラウザは画面から入力されたデータだけをWebサーバに送信しているのではない
  • HTTPリクエストは擬似ヘッダフィールドとヘッダフィールドに分かれる
  • GETリクエストの場合、画面から入力したデータはリクエストライン( :path 擬似ヘッダフィールド)に含まれる