WebアプリでのHTTP GETとPOSTの比較

はじめに

GETとPOSTの比較

GETメソッドはページを取得するため、POSTはデータをサーバに送信するために使用されます。
両者の違いは次の通りです。

観点 GET POST
データ定義場所 URIに付加(クエリ文字列)
(ボディ部へのデータ指定はサポート外 ※1)
主にボディに付加
(URIにも付加可)
データ可視性 データはURIに付加されるので誰でも確認可 データはURIに付加されないので簡単には確認不可
戻る・再読み込み 問題なし データが再送信される。※2
フォームを再送信するかを確認するダイアログが表示される。
ブックマーク保存 保存可能 保存不可 ※3
キャッシュ化 キャッシュされる キャッシュされない
エンコーディング なし application/x-www-form-urlencoded
(バイナリ送信のマルチパート使用時はmultipart/form-data)
ブラウザ履歴 履歴上に残る。
(履歴の保存対象となるURIにデータがあるため。)
データは履歴に保存されない。
データ長の制限 データを付加したURIは約2000文字以下が安全 ※4 制限なし ※5
データ種類の制限 ASCII文字のみ許可 制限はなく、バイナリデータの使用も可
安全性 POSTより低い
パラメータがURI上に付加される、ブラウザ履歴やサーバ側のアクセスログに残るため。
パスワード等の機微なデータは扱えない。
GETより安全
パラメータはURIに付加されないため、ブラウザ履歴やアクセスログに残らない。
  • ※1: GETはURIで指定されたリソースを受け取ることに主眼が置かれており、ボディにデータを指定する方法は想定していません。
    • HTTP1.0を規定するRFC1945, HTTP1.1を規定するRFC2068, RFC2616では、GETでのボディ指定は明記されていません。
    • 改訂版のRFC7231(Section 4.3.1)では、GETのボディは一部のシステムで拒否される可能性がある、旨の記載があります。

      A payload within a GET request message has no defined semantics;
      sending a payload body on a GET request might cause some existing
      implementations to reject the request.

    • 互換性を考えるとGET時のボディ設定は回避した方が安全です。
    • 詳細はこちらを参考のこと。
  • ※2: POSTで表示されたページURIをブックマークすると同URIをGETするブックマークが保存されるます。そのため、保存されたブックマークを開いた際の挙動は実装に依存します。
  • ※3: 戻る・進む・再読み込みで更新データが重複登録されるのを回避するために画面遷移方式としてPRGパターン(Post/Redirect/Get)が使用されます。
  • ※4: ブラウザやサーバで扱えるURIの上限は次の通りです。
    • HTTP1.1を規定するRFC2616等では上限を決めておらず、改訂版のRFC7230では8000オクテットが推奨されましたが、現在ではブラウザ・サーバ依存の状況になっているようです。例えばChromeでは2MB、Apache HTTPサーバでは8KBだったりします。
    • 過去のブラウザやサーバとの互換性を考えるなら上限2000文字が安全のようです。特定のブラウザ・サーバ環境を使用するのであれば、その環境で許容される最大長を使用できます。
    • なお、この上限を超える場合はサーバ側で応答コード414(URI Too Long)を返却します。
    • 詳細はこちらを参考のこと。
  • ※5: HTTPの仕様として上限はありませんが、一般的なWebサーバではDoS攻撃を回避するために既定でPOSTデータの上限サイズを設けています。例えばWildflyの既定の上限サイズは10MBになっています。

業務実装での考察

  • 検索画面における検索実行はGETでやるかPOSTでやるか?
    • 経験的に以前は「画面初期表示はGET、検索実行はPOST」としていたが、画面表示も検索もデータの検索・取得系の処理要求なのでGETの方がメソッドの目的に合致する。
    • 検索条件を指定して検索画面を開くようなケースではGETの方が容易に実現できる。
      (URIに検索条件をクエリ文字列として付与するだけで実現可。POSTの場合はフォームデータの作成等の処理が必要となりGETより手間がかかる。)

      • メールに記載された処理結果確認用URIを開き、処理結果を直接開くような場合
      • 登録完了後に検索画面で登録結果を初期表示するような場合
      • 一覧画面で対象を選択して編集後、同じ条件で一覧画面を表示する場合(編集後に同一の検索条件を復元)
    • 金融や物流等の検索画面では検索条件が10~20項目以上ある場合もある。このようなケースではクエリ文字列が非常に長くなるのでPOSTの方が適しているかもしれない。
    • 検索条件として画像等のバイナリを扱う場合、GETでは実現できないので、POSTを使用する必要がある。
    • 検索画面に関して、基本はGETを使用するが検索条件項目が多い(例えば10個以上)場合はPOSTを使用、等の設計ルール(標準化)が良いかもしれない。
    • RESTfulの場合、POSTオーバーロード(POSTに複数の役割・機能も持たせる)という方式で複雑な検索条件を実現することもできる。