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

はじめに

GETとPOSTの比較

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

観点GETPOST
データ定義場所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に複数の役割・機能も持たせる)という方式で複雑な検索条件を実現することもできる。