はじめに
- 業務Webアプリの開発で、検索画面の実装で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の上限は次の通りです。
- ※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に複数の役割・機能も持たせる)という方式で複雑な検索条件を実現することもできる。リンク