PHP - WEB - 6. HTTPリクエストの詳細(POSTリクエスト)

引き続きHTTPリクエストについて学習していきましょう。

繰り返しになりますが HTTPリクエストは以下の3つのパートで構成されています。

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

先ほど学習したGETリクエストの場合は、リクエストラインとヘッダフィールドは利用しているものの、ボディパートの利用はありませんでした。

次はPOSTリクエストについて詳しく検証していきましょう。

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

続いてログインプログラム( login.html )について POST リクエストを送信するように修正してみましょう。

<!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="post">
        <input type="text" name="id">
        <input type="password" name="password">
        <input type="submit" value="login">
    </form>
</body>
</html>

form タグの method 属性を post に修正します。

同様にPOSTリクエストを処理するプログラム( login.php )も $_GET 変数から $_POST 変数に修正します。

<?php
$id = $_POST["id"];
$password = $_POST["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>

それでは実際にPOSTリクエストのキャプチャーを取得してみましょう。まずは以下のURLを入力してログイン画面( login.html )にアクセスします。

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

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

次のこの通信データをクリックすると次のように表示されるでしょう。画面をスクロールすると「Request Headers」というセクションがあります。

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

:authority: c6327f0f708344ba914531f340671547.vfs.cloud9.ap-northeast-1.amazonaws.com
:method: POST
:path: /login.php
: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
cache-control: max-age=0
content-length: 23
content-type: application/x-www-form-urlencoded
cookie: __Host-previewc9corsvfs_9c0d5j7Z1PFSFxRo=9ck6M6IHHfbozVDiAEl36pzUcbrA5FKq; AWSALB=PrEQhlGUx2qXjtx6MhYPSLs69ju34skNpD4swd2nM8vKSMYO35cBxm3XagFkKenmo9naMApd6uzKg9AEiA8J+iiN5q2h/DndkSYeJIjEDaQJYHu3G6ojiWhXQk1r; AWSALBCORS=PrEQhlGUx2qXjtx6MhYPSLs69ju34skNpD4swd2nM8vKSMYO35cBxm3XagFkKenmo9naMApd6uzKg9AEiA8J+iiN5q2h/DndkSYeJIjEDaQJYHu3G6ojiWhXQk1r
origin: https://c6327f0f708344ba914531f340671547.vfs.cloud9.ap-northeast-1.amazonaws.com
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リクエストの1つ目のパートであるリクエストラインと2つ目のパートであるヘッダフィールドの情報です。ここまでの内容は GET リクエストの場合とよく似ています。ここでは :method:path に注目してください。

:method: POST
:path: /login.php

:method 擬似ヘッダフィールドの値が POST となっていることがわかるでしょう。また :path 擬似ヘッダフィールドには GETリクエストのように画面から入力されたデータ( ?id=Andy&password=secret )が付与されていない点に気づくでしょう。

それでは画面から入力されたデータはどのように送信されるのでしょうか。実はPOSTリクエストの場合は、画面から入力されたデータを :path の一部として送信するのではなく、HTTPリクエストのボディパートと呼ばれる領域に含んで送信するようになっています。

HTTPでは送信データを大別すると「ヘッダフィールド(リクエストライン含む)」と「ボディパート」の2つの領域が用意されています。GETリクエストではボディパートは利用しませんでしたが、POSTリクエストではボディパートを利用するという仕組みになっています。

デベロッパーツール上で Payload タブを選択すると「Form Data」というセクションがあります。ここに表示されている内容がHTTPリクエストのボディパートに含まれる送信データです。

ここには画面から入力したパラメータが次のように表示されているのがわかります。

id: Andy
password: secret

このようにPOSTリクエストの場合は、ヘッダフィールド(擬似ヘッダフィールド含む)だけを送信するのではなく、それに加えてボディパートに画面から入力されたデータを格納して送信します。

GETリクエストとPOSTリクエストの違い

GETリクエストとPOSTリクエストの違いを整理すると次のようになります。

GETリクエスト POSTリクエスト
リクエストライン
(擬似ヘッダフィールド)
:method: GET
:path に入力データを付加する
:method: POST
ヘッダフィールド 自動的に様々なヘッダが付加される 自動的に様々なヘッダが付加される
ボディパート 利用しない 入力データを含む

GETリクエストは :path に入力データを付加するため、ブラウザ上ではアドレスバーにリクエストパラメータが見えるようになります。

このような挙動はログイン機能には不向きですが、検索機能で有効に機能します。GETリクエストの特徴である「URLに入力パラメータが付与される」という点はURLを再利用できるというメリットがあります。具体的にはURLをお気に入りに登録しておくなどしてパラメータ付きのURLを再利用できます。

一方でPOSTリクエストの場合は、画面からの入力データはボディパートに格納されるので、ユーザの目に触れにくくなります。

ログイン機能のようなケースではPOSTリクエストを使うことが自然でしょう。

POSTリクエストを使えば安全に送信できる、というわけではない点に注意してください。デベロッパーツールのようなネットワークの通信データをキャプチャーするソフトウェアを使えば、簡単に入力データを盗み見ることができます。暗号化のような安全な通信を確保するには https のような仕組みを利用する必要があります。

他にもユーザ作成処理であったり、ショッピングカートの購入処理であったり、サーバ上に何かデータを作成(更新、削除)する場合はPOSTリクエストを送信することが一般的です。

まとめ

  • GETリクエストとPOSTリクエストでデータの送信方法が異なる
  • GETリクエストはリクエストパラメータをリクエストライン(擬似ヘッダフィールド)に含む
  • POSTリクエストはリクエストパラメータをボディパートに含む