APIのGETとPOSTメソッド、違いと使い分けを徹底解説!
Webアプリケーションやシステムの開発において、API(Application Programming Interface)は不可欠な要素となっています。APIを通じて、異なるシステムやサービスが互いに連携し、データをやり取りします。このデータ通信の基盤となっているのが、HTTP(Hypertext Transfer Protocol)です。そして、HTTPにおけるデータ通信の「目的」や「操作」を表現するのが「HTTPメソッド」です。
HTTPメソッドの中でも、最も基本的で頻繁に利用されるのがGET
メソッドとPOST
メソッドです。これら二つのメソッドは、一見するとどちらもサーバーとデータをやり取りするための手段のように見えますが、その目的、データの送信方法、性質、そして使い分けには明確な違いがあります。
本記事では、このHTTPの二大メソッドであるGET
とPOST
に焦点を当て、それぞれの特徴、違い、そしてどのような状況でどちらを使うべきかについて、徹底的に、そして詳細に解説していきます。API設計やWeb開発に関わるすべての方にとって、これらのメソッドの本質を理解することは、安全で効率的、かつ保守性の高いシステムを構築するために非常に重要です。
1. なぜHTTPメソッドを知る必要があるのか? APIとHTTPの基本
GETとPOSTの詳細に入る前に、まずはAPIとHTTPの基本的な関係性について確認しておきましょう。
1.1 APIとは?
APIは「Application Programming Interface」の略で、文字通り「アプリケーションをプログラミングするためのインターフェース」です。これは、あるソフトウェアコンポーネントが、別のソフトウェアコンポーネントとどのように情報をやり取りするかを定義する一連のルールや仕様のことです。
例えば、Web APIの場合、これはWebサーバー上の特定の機能(リソース)にアクセスするための窓口となります。クライアント(例えばWebブラウザやモバイルアプリ)は、このAPIを通じてサーバーにリクエストを送り、サーバーはそれに応じた処理を実行してレスポンスを返します。
1.2 HTTPプロトコルとは?
多くのWeb APIは、HTTP(Hypertext Transfer Protocol)というプロトコル上で動作します。HTTPは、クライアントとサーバー間でデータを送受信するための通信規約です。クライアントがサーバーに「リクエスト」を送信し、サーバーがそれに対して「レスポンス」を返す、という形式で通信が行われます。
このHTTPリクエストには、通信の様々な情報が含まれていますが、その中でも特に重要なのが「HTTPメソッド」です。
1.3 HTTPメソッドの役割
HTTPメソッドは、クライアントがサーバー上の指定された「リソース」(例えば、特定のデータ、ファイル、機能など)に対して、どのような「操作」を行いたいのかを示すために使われます。
HTTP/1.1では、いくつかの標準的なメソッドが定義されています。主なものとしては以下の通りです。
- GET: リソースを取得する。
- POST: データを送信し、新しいリソースを作成したり、特定のアクションを実行したりする。
- PUT: 指定したURIにリソースを完全に置き換える。
- DELETE: 指定したリソースを削除する。
- PATCH: リソースの一部を変更する。
- HEAD: GETと同じだが、レスポンスボディは返さずヘッダー情報のみを取得する。
- OPTIONS: 対象リソースがサポートしているメソッドを確認する。
これらのメソッドは、リソースに対するCRUD(Create, Read, Update, Delete)操作や、その他のアクションを表現するために利用されます。
この記事で深く掘り下げるGET
とPOST
は、これらのメソッドの中でも最も基本的な「読み取り(Read)」と「作成/更新(Create/Update)あるいはアクションの実行」に対応するものです。これらの違いを正しく理解することは、APIを効果的に利用・設計する上で最初の、そして最も重要なステップとなります。
2. GETメソッドの詳細:リソースを取得する
GET
メソッドは、サーバーから指定されたリソースを取得するために設計されています。これは、WebブラウザでURLを入力してWebページを表示したり、画像ファイルを取得したり、APIから特定のデータを取得したりする際に最も一般的に使用されるメソッドです。
2.1 GETメソッドの定義と目的
GET
メソッドの唯一の目的は、「サーバー上のリソースの現在の状態を取得すること」です。クライアントは、サーバー上の特定のURI(Uniform Resource Identifier)を指定してGETリクエストを送信します。サーバーは、そのURIに対応するリソースを見つけ出し、その内容をHTTPレスポンスのボディとしてクライアントに返します。
2.2 GETメソッドの主な特徴
GET
メソッドには、その目的から派生するいくつかの重要な特徴があります。
- データの取得のみ:
GET
リクエストは、サーバーからデータを「読み取る」ためだけに使用されます。これは、サーバー側のリソースの状態を変更しないという厳格なルールに基づいています。 - 安全性 (Safe):
GET
リクエストは「安全」であると定義されます。これは、リクエストを何度実行しても、サーバー上のリソースの状態に変更を及ぼさないことを意味します。例えば、Webページを何度リロードしても、ページの内容は表示されるだけで、サーバー側のデータが勝手に変更されることはありません。 - 冪等性 (Idempotent):
GET
リクエストは「冪等」であると定義されます。これは、同じリクエストを複数回繰り返し実行しても、1回実行した場合と同じ結果が得られることを意味します。データの取得操作なので、これは当然の性質と言えるでしょう。例えば、特定のユーザー情報を取得するGETリクエストを10回送信しても、毎回同じユーザー情報が返ってくるはずです。 - データの送信方法 (クエリパラメータ): クライアントからサーバーに何らかの情報を渡したい場合(例えば、検索キーワード、フィルタリング条件、取得したいリソースのIDなど)、
GET
メソッドでは通常、URLの一部であるクエリパラメータとしてデータを送信します。クエリパラメータは、URLのパス部分の後ろに?
を付け、キー=値
の形式で記述し、複数のパラメータは&
で連結します。
例:/users?id=123&fields=name,email
- リクエストボディ:
GET
メソッドはリクエストボディを持つべきではないとHTTPの仕様(RFC 7231など)で定められています。これは、GETの目的が「リソースの取得」であり、サーバーに何か新しいデータを作成/更新/送信することではないからです。多くのサーバーやプロキシはGETリクエストのボディを無視します。 - キャッシュ可能:
GET
リクエストとそのレスポンスは、クライアント(ブラウザなど)やプロキシサーバーによってキャッシュされることが可能です。一度取得したリソースが頻繁に変化しない場合、キャッシュを利用することで、次回同じリクエストがあった際にサーバーにアクセスすることなく、キャッシュから素早くレスポンスを返すことができます。これは通信量の削減や表示速度の向上に繋がります。 - ブラウザのアドレスバーからのアクセス:
GET
リクエストは、WebブラウザのアドレスバーにURLを直接入力して実行できます。これは、クエリパラメータを含むURLも同様です。 - ブックマーク可能:
GET
リクエストのURL(クエリパラメータを含む)は、ブラウザのブックマークとして保存し、後で同じ状態のリソースに再びアクセスすることが可能です。 - ブラウザの履歴に残る:
GET
リクエストはブラウザの履歴に記録されます。これにより、ユーザーは以前アクセスしたページや検索結果に簡単に戻ることができます。 - クエリパラメータの長さ制限: URL全体の長さには、ブラウザやサーバーによって技術的な制限が存在します。そのため、あまりに大量のデータをクエリパラメータとして送信することは推奨されません。通常、数キロバイト程度が実質的な上限となることが多いです。
2.3 GETメソッドの使いどころ
これらの特徴を踏まえると、GET
メソッドは以下のようなケースで適切に利用されます。
- Webページの表示: ほとんどのWebサイトへのアクセスはGETリクエストです。
- リソースの一覧取得: 例: ユーザー一覧、商品リスト、記事一覧など。
GET /users
GET /products
GET /articles
- 特定のリソースの詳細取得: 例: 特定のユーザー情報、特定の商品詳細、特定の記事内容など。
GET /users/123
GET /products/abc-456
GET /articles/the-power-of-api
- 検索機能: 検索キーワードをクエリパラメータとして送信し、一致するリソースを取得します。
GET /search?query=API+guide
- フィルタリング、ソート、ページネーション: 一覧取得の際に、条件や表示順、表示範囲などをクエリパラメータで指定します。
GET /products?category=electronics&sort=price_asc&page=2
- 画像、CSSファイル、JavaScriptファイルなどの静的ファイルの取得:
GET /images/logo.png
GET /css/style.css
2.4 GETメソッドの注意点
GET
メソッドはリソースの取得に特化しており、安全かつ冪等であるという性質から非常に扱いやすいメソッドですが、利用する際にはいくつかの注意点があります。
- 機密情報の送信: クエリパラメータとして送信されるデータは、URLの一部として扱われます。これは、ブラウザの履歴、サーバーのログ、プロキシサーバーなどで容易に記録・参照される可能性があることを意味します。したがって、パスワード、クレジットカード情報、APIキーなどの機密性の高い情報をクエリパラメータに含めて送信してはいけません。
- サーバーの状態変更:
GET
メソッドはサーバー側の状態を変更すべきではありません。例えば、「ユーザーを削除する」という操作をGET /users/delete/123
のようなURLで行うのは間違った使い方です。ユーザーがこのURLを意図せずクリックしたり、ブラウザがプリフェッチ機能で勝手にアクセスしたりするだけで、ユーザーが削除されてしまう可能性があります。状態変更操作には、後述するPOST
やDELETE
などのメソッドを使用する必要があります。 - 大規模なデータの送信: クエリパラメータには長さ制限があるため、大量のデータをサーバーに送信する必要がある場合には不向きです。例えば、長文の記事内容を送信するようなケースです。
これらの点を踏まえると、GET
メソッドは「サーバーから何かを取得するだけであり、その操作自体によってサーバー側のデータが変わってしまうような副作用があってはならない」という原則を常に念頭に置いて利用・設計することが重要です。
3. POSTメソッドの詳細:データを送信し、リソースを操作する
POST
メソッドは、クライアントからサーバーにデータを送信し、サーバー側でそのデータに対して何らかの処理を実行するために使用されます。これは、新しいリソースを作成したり、既存のリソースを更新したり、あるいは特定のビジネスロジックをトリガーしたりする際に利用されます。
3.1 POSTメソッドの定義と目的
POST
メソッドの主な目的は、「クライアントから送信されたデータを、指定されたリソースに紐づけてサーバーが処理する」ことです。その処理の結果として、新しいリソースが作成されたり、既存のリソースが更新されたり、あるいはその他の副作用(例えば、メール送信やログ記録など)が発生したりします。
3.2 POSTメソッドの主な特徴
POST
メソッドは、GET
メソッドとは対照的に、サーバーの状態を変更する可能性がある操作のために設計されています。そのため、GET
とは異なるいくつかの重要な特徴を持ちます。
- データの送信と操作:
POST
リクエストは、クライアントがサーバーにデータを「送信」し、サーバー側でそのデータを用いて「操作」を実行するために使用されます。これは、リソースの作成、更新、あるいは特定の「アクション」の実行を伴います。 - 安全性がない (Not Safe):
POST
リクエストは「安全ではない」と定義されます。これは、リクエストを実行することで、サーバー上のリソースの状態が変更される可能性があることを意味します。例えば、ブログ記事を投稿するPOSTリクエストを送信すると、サーバー上に新しい記事データが作成されます。 - 冪等性がない (Not Idempotent):
POST
リクエストは通常「冪等ではない」と定義されます。これは、同じリクエストを複数回繰り返し実行すると、1回実行した場合とは異なる結果になる可能性が高いことを意味します。例えば、新しいユーザーを作成するPOSTリクエストを2回送信すると、通常は同じユーザーが2回作成されてしまいます。ただし、サーバー側の実装によっては、冪等になるように設計することも不可能ではありません(例:ユニークなIDをクライアント側で生成して送信し、サーバー側で重複をチェックするなど)。しかし、メソッド自体の定義としては冪等ではありません。 - データの送信方法 (リクエストボディ):
POST
メソッドでは、クライアントからサーバーに送信するデータは、HTTPリクエストのリクエストボディに格納されます。リクエストボディには、様々な形式のデータを含めることができます(例:HTMLフォームデータ、JSON、XML、バイナリデータなど)。データの形式は、Content-Type
ヘッダーで指定します。 - リクエストボディのデータ量: リクエストボディにデータを格納するため、
GET
メソッドのクエリパラメータのような厳格な長さ制限は通常ありません。送信できるデータ量は、サーバー側の設定(最大リクエストボディサイズなど)に依存しますが、クエリパラメータよりもはるかに大きなデータを送信することが可能です。 - キャッシュ:
POST
リクエストとそのレスポンスは、基本的にキャッシュされません。これは、POST
がサーバーの状態を変更する可能性があり、同じリクエストでも状況によって結果が変わる可能性があるためです。ただし、レスポンスヘッダーでキャッシュを許可するように明示的に指定することも技術的には可能ですが、一般的ではありません。 - ブラウザのアドレスバーからのアクセス:
POST
リクエストは、WebブラウザのアドレスバーにURLを直接入力して実行できません。POSTリクエストは、通常、HTMLフォームの送信やJavaScriptによるAPI呼び出しによって行われます。 - ブックマーク不可:
POST
リクエストは、リクエストボディにデータが含まれるため、URLだけをブックマークしても同じリクエストを再現できません。 - ブラウザの履歴:
POST
リクエストのURLはブラウザの履歴に残りますが、リクエストボディに含まれる実際のデータは通常残りません。 - フォーム送信: HTMLフォームの
method="post"
属性は、POSTメソッドを使用してフォームデータをサーバーに送信します。
3.3 POSTメソッドの使いどころ
これらの特徴を踏まえると、POST
メソッドは以下のような、サーバー側の状態を変更したり、サーバーで特定の処理を実行したりするケースで適切に利用されます。
- 新しいリソースの作成: データベースに新しいレコードを追加するなど。
- 例: ユーザー登録、ブログ記事投稿、コメント追加、商品の注文など。
POST /users
(リクエストボディに新しいユーザー情報)POST /articles
(リクエストボディに新しい記事の内容)POST /orders
(リクエストボディに注文情報)
- 既存のリソースの更新(一部または全体):
- 例: ユーザープロフィールの変更、記事内容の編集など。
PUT
メソッドも更新に使われますが、POST
は「指定されたリソースに対して、リクエストボディのデータを使って何かをする」という、より汎用的な意味合いで使われることがあります。例えば、リソースの一部だけを変更する場合や、特定のフィールドだけを更新する場合などです。(より厳密なRESTfulな設計では、リソース全体を置き換える場合はPUT
、一部を更新する場合はPATCH
を使うことが多いですが、POST
を更新に使うAPIも存在します。) POST /users/123
(リクエストボディに更新データ)POST /articles/the-power-of-api
(リクエストボディに編集後の内容)
- 例: ユーザープロフィールの変更、記事内容の編集など。
- サーバー側で処理が必要なフォームデータの送信: お問い合わせフォーム、ログインフォームなど、ユーザーが入力したデータをサーバーに送信して処理する場合。
POST /contact
(リクエストボディにお問い合わせ内容)POST /login
(リクエストボディにユーザーID/パスワード)
- ファイルのアップロード: 画像ファイルやドキュメントファイルなどをサーバーに送信する場合。リクエストボディにバイナリデータを含めて送信します。
POST /upload
(リクエストボディにファイルデータ)
- 特定の「アクション」の実行: APIエンドポイントが特定のリソースではなく、「処理」自体を表す場合。
- 例: メール送信、データのエクスポート、複雑なレポート生成のキックなど。
POST /send-email
(リクエストボディに送信内容)POST /export-data
(リクエストボディにエクスポート条件)
3.4 POSTメソッドの注意点
POST
メソッドはサーバーの状態を変更する可能性があるため、利用する際にはいくつかの注意点があります。
- 冪等性がないことの理解:
POST
リクエストは冪等ではないため、安易に同じリクエストを繰り返し送信すると、意図しない結果(データの重複作成など)を招く可能性があります。 - POSTリロード問題: WebブラウザでPOSTリクエストを送信した後、ユーザーがページの再読み込み(リロード)を行うと、ブラウザは「同じPOSTリクエストを再度送信しますか?」という警告を表示することがあります。ユーザーが同意すると、同じリクエストが二重に送信されてしまい、データの二重登録などを引き起こす可能性があります。これを避けるための一般的なパターンとして、PRGパターン (Post/Redirect/Get) があります。POSTリクエストの処理が成功したら、クライアントに別のURL(通常はGETリクエストでアクセスする結果表示ページなど)へリダイレクトさせることで、リロード時にPOSTが再送信されるのを防ぎます。
- セキュリティ: リクエストボディのデータはURLに含まれないため、GETのクエリパラメータよりは盗聴のリスクは低いですが、通信経路が暗号化されていない(HTTPの場合)場合は傍受される可能性があります。機密情報を扱う場合は、必ずHTTPSを使用して通信を暗号化する必要があります。
これらの点を踏まえると、POST
メソッドは「クライアントからサーバーにデータを渡し、サーバー側でそのデータを用いて、リソースの作成や変更といった副作用を伴う処理を実行する」という目的で利用することが適切です。
4. GETとPOSTの決定的な違いを比較!
ここまで見てきたGETとPOSTの定義、特徴、使いどころ、注意点をまとめると、その違いはより明確になります。以下の比較表は、両者の主要な違いを一覧にしたものです。
特徴 | GET | POST |
---|---|---|
目的 | サーバーからリソースを取得する | サーバーにデータを送信し、リソースを操作する(作成/更新/アクション実行) |
安全性 (Safe) | ある(リソースの状態を変更しない) | ない(リソースの状態を変更する可能性がある) |
冪等性 (Idempotent) | ある(複数回実行しても結果は同じ) | ない(複数回実行すると結果が変わる可能性がある) |
データの送信方法 | URLのクエリパラメータとして送信 | HTTPリクエストボディに格納して送信 |
リクエストボディ | 基本的に持たない(持っても無視されることが多い) | 持つ |
データ量制限 | クエリパラメータの長さに制限がある(ブラウザ/サーバー依存、数百バイト~数キロバイト程度) | リクエストボディのサイズに制限があるが、GETよりはるかに大きいデータを送れる(サーバー設定依存) |
キャッシュ | 可能 | 基本的に不可能 |
ブラウザのアドレスバーからのアクセス | 可能 | 不可能 |
ブックマーク | 可能 | 不可能 |
ブラウザ履歴 | URLとクエリパラメータが残る | URLは残るが、リクエストボディのデータは残らない |
フォーム送信 | <form method="get"> |
<form method="post"> |
用途の例 | Webページ表示、検索、一覧表示、詳細表示 | フォーム送信(登録、投稿、購入)、ファイルアップロード、ログイン、アクション実行 |
副作用 | なし | あり(リソースの作成、変更など) |
この比較表を見れば、GETとPOSTが全く異なる目的のために設計されていることが一目瞭然です。API設計においては、これらの性質を理解し、実現したい操作の性質に応じて適切なメソッドを選択することが極めて重要です。
5. 使い分けの具体的なシナリオ
GETとPOSTの基本的な違いを踏まえ、実際の開発においてどのように使い分けるべきかを具体的なシナリオで見ていきましょう。
5.1 GETメソッドを使うべきケース
- Webサイトのトップページや特定のページを表示する場合:
GET /
GET /about
GET /contact
目的はページのHTMLコンテンツを取得することであり、サーバー側の状態は変更されません。
- ユーザー一覧、商品リスト、記事一覧などを表示する場合:
GET /users
GET /products
GET /articles
リソースの一覧を取得する操作であり、これもサーバー側の状態を変更しません。
- 特定のユーザー情報、商品詳細、記事内容などを表示する場合:
GET /users/123
GET /products/abc-456
GET /articles/the-power-of-api
特定の単一リソースを取得する操作であり、サーバー側の状態は変更されません。
- 検索機能の実装:
GET /search?query=keyword
GET /products?name=laptop&category=electronics
検索キーワードや条件をクエリパラメータで渡し、それに合致するリソースを取得します。検索操作自体はサーバーの状態を変更しません。
- フィルタリング、ソート、ページネーションを含む一覧表示:
GET /articles?tag=technology&sort=date_desc&page=1&limit=10
クエリパラメータで取得条件を指定しますが、これもリソースの絞り込みや並べ替えを行うだけで、サーバー側のデータ自体を変更するものではありません。
- 画像の表示、CSSやJavaScriptファイルの読み込み:
GET /images/photo.jpg
GET /css/style.css
静的なファイルを取得する操作であり、もちろんサーバーの状態を変更しません。
GETは、単に情報を「見たい」「取得したい」 という場合に適しています。ブラウザでURLをコピー&ペーストして共有したり、ブックマークに保存したりできるという利便性も、取得操作であるGETの性質と非常に相性が良いです。
5.2 POSTメソッドを使うべきケース
- 新しいリソースを作成する場合:
- ユーザー登録:
POST /users
(リクエストボディに新しいユーザー情報) - ブログ記事投稿:
POST /articles
(リクエストボディに記事の内容) - コメント追加:
POST /articles/the-power-of-api/comments
(リクエストボディにコメント内容) - 商品の注文:
POST /orders
(リクエストボディに注文情報)
これらの操作は、データベースに新しいデータを追加するなど、サーバー側の状態を大きく変更します。複数回実行すると、同じデータが重複して作成される可能性があります(例:同じユーザーが2回登録される)。
- ユーザー登録:
- 既存のリソースの一部または全体を更新する場合:
- ユーザープロフィールの更新:
POST /users/123
(リクエストボディに更新したいプロフィール情報) - 記事の編集:
POST /articles/the-power-of-api
(リクエストボディに編集後の内容)
これはリソースの状態を変更する操作です。厳密なRESTfulではPUT
やPATCH
が使われることもありますが、POST
も更新の用途で広く使われます。
- ユーザープロフィールの更新:
- フォーム送信(ユーザーが入力したデータをサーバーに送信して処理する場合):
- お問い合わせフォーム:
POST /contact
(リクエストボディにお問い合わせ内容) - ログイン処理:
POST /login
(リクエストボディにユーザーIDとパスワード)
お問い合わせ内容はサーバーで処理(メール送信やデータベース保存など)され、ログイン処理は認証状態をサーバー側で変更します。特にログインのような機密情報を含むデータは、リクエストボディで送信するPOSTが適しています。
- お問い合わせフォーム:
- ファイルのアップロード:
POST /upload
(リクエストボディにファイルデータ)
ファイルデータは通常大きいため、リクエストボディで送信できるPOSTが必須です。
- 特定の「アクション」を実行する場合:
- メール送信機能:
POST /send-email
(リクエストボディに送信先や内容) - レポート生成のトリガー:
POST /generate-report
(リクエストボディにレポート条件)
これらの操作は、リソースの作成や更新というよりも、サーバー側で定義された特定のビジネスロジックを実行することが目的です。このような「リモートプロシージャコール (RPC) 的な」操作にはPOSTが使われることが多いです。
- メール送信機能:
POSTは、サーバーに何かを「したい」「実行してほしい」 という場合に適しています。特に、その操作によってサーバー側のデータが変更される場合や、機密情報を送信する場合、大量のデータを送信する場合に選択します。
6. RESTful APIにおけるGETとPOSTの役割
現代の多くのAPIは、REST(Representational State Transfer)という設計原則に基づいて構築されています。RESTful APIでは、URIが「リソース」を表現し、HTTPメソッドがそのリソースに対する「操作」を表現するという考え方が重要視されます。
RESTfulな設計におけるHTTPメソッドのマッピングは以下のようになります。
- GET /resources : リソースの集合を取得する (Read Collection)
- GET /resources/{id} : 特定のリソースを取得する (Read Item)
- POST /resources : 新しいリソースを作成する (Create)
- PUT /resources/{id} : 特定のリソースを、リクエストボディのデータで完全に置き換える (Update/Replace)
- PATCH /resources/{id} : 特定のリソースの一部を、リクエストボディのデータで更新する (Update/Partial Update)
- DELETE /resources/{id} : 特定のリソースを削除する (Delete)
この文脈において、GET
は純粋な読み取り(Read) 操作に対応します。サーバーの状態を変更しない、安全で冪等な操作として利用されます。
一方、POST
は主に新しいリソースの作成(Create) に対応します。POST /resources
のように、リソースの集合(コレクション)のURIに対してPOSTリクエストを送信し、リクエストボディに含まれるデータを使って、そのコレクションに新しいリソースを追加するというパターンが典型的です。
また、RESTfulな設計では、リソースに対するCRUD操作に厳密にマッピングできないような特定の「アクション」を実行したい場合にもPOST
が利用されることがあります。例えば、ユーザーをアクティベートする /users/{id}/activate
や、注文を確定する /orders/{id}/confirm
のようなエンドポイントに対してPOSTリクエストを送信する、といったパターンです。これはリソースの「状態」を変更する操作であり、冪等性がない可能性があるため、POSTが適切とされます。
PUTとPOSTはどちらもリソースの更新に使われることがありますが、RESTfulな観点からは違いがあります。
- PUT: 指定されたURIにリソースが「あるべき状態」をリクエストボディで送信し、完全に置き換える操作です。冪等性があります(同じPUTを何度実行しても、結果としてリソースはリクエストボディの状態になります)。
- POST: 指定されたリソースに対して、リクエストボディのデータを用いて何かをする操作です。新しいリソースの作成が典型的ですが、リソースの一部更新や特定のアクションの実行にも使われます。冪等性はありません。
したがって、RESTful APIを設計する際には、リソースの状態変更を伴う操作かどうか、冪等性があるかどうかなどを考慮して、POST、PUT、PATCHといったメソッドを適切に使い分けることが推奨されます。しかし、GETとPOSTに関しては、その基本的な「取得」と「送信/操作」という役割分担は、RESTfulかどうかにかかわらず共通の原則として非常に重要です。
7. 技術的な補足と発展的な内容
GETとPOSTの違いや使い分けをより深く理解するために、関連する技術的な概念や注意点についても触れておきましょう。
7.1 冪等性 (Idempotency) と安全性 (Safety) の重要性
HTTPメソッドの「安全性」と「冪等性」は、APIの挙動を予測可能にし、クライアント側(特にブラウザ)やネットワークインフラストラクチャ(プロキシ、キャッシュなど)がどのようにリクエストを扱えるかを決定するための重要な特性です。
- 安全性 (Safety): 安全なメソッド(GET, HEAD, OPTIONS, TRACE)は、サーバー上のリソースの状態を変更する副作用を持ちません。これにより、ブラウザはユーザーの許可なくこれらのリクエストをプリフェッチしたり、リンクをたどる際に自動的に実行したりすることができます。検索エンジンのクローラーも安全なリクエストのみを行います。
GET
は安全なので、リンクとして配置したり、ブラウザのアドレスバーからアクセスしたりしても問題ありません。 - 冪等性 (Idempotency): 冪等なメソッド(GET, HEAD, OPTIONS, TRACE, PUT, DELETE)は、同じリクエストを何度実行しても、初回実行後のリソースの状態が同じになります。これは、ネットワークの不確実性(タイムアウトやエラー)によりリクエストが再試行される可能性がある場合に重要です。クライアントやプロキシは、冪等なリクエストであれば、応答が返ってこなかった場合に安全にリトライできます。
GET
はデータの取得なので冪等です。PUT
はリソース全体を置き換えるので、何度置き換えても結果は同じ状態になるため冪等です。DELETE
も、一度削除されれば、その後の同じDELETEリクエストはリソースが存在しないという同じ結果になる(ただしステータスコードは異なる場合がある)ため冪等と見なされます。
POST
は通常、安全でも冪等でもありません。新しいリソースを作成するPOSTを複数回実行すると、リソースが複数作成されてしまいます。安全でないため、ブラウザはユーザーの明示的な操作(フォームの送信など)なしにPOSTリクエストを自動で送信することはありません。冪等でないため、ネットワークエラー発生時のリトライは、サーバー側で二重送信の可能性を考慮した特別な処理が必要になります。
7.2 キャッシュ制御とGET/POST
HTTPのキャッシュ機構は、主に安全かつ冪等なメソッド、特にGETリクエストに対して機能するように設計されています。サーバーはレスポンスヘッダー(Cache-Control
, Expires
, ETag
, Last-Modified
など)を通じて、レスポンスをどのくらいの期間キャッシュして良いか、キャッシュが有効かどうかなどをクライアントやプロキシに指示できます。
GETリクエストのレスポンスがキャッシュされている場合、同じGETリクエストが再び送信されたとき、クライアントやプロキシはサーバーに問い合わせることなくキャッシュされたレスポンスを返すことができます(または、キャッシュが有効かどうかをサーバーに確認するだけの場合もあります)。これにより、パフォーマンスが向上し、サーバー負荷やネットワークトラフィックが削減されます。
一方、POSTリクエストはサーバーの状態を変更する可能性があるため、そのレスポンスはデフォルトではキャッシュされません。同じURLへのPOSTリクエストであっても、毎回サーバーで処理が実行され、新しい結果が返されることが期待されます。
7.3 POSTリロード問題とPRGパターン
前述したPOSTリロード問題(POST送信後にブラウザをリロードすると二重送信される問題)は、POSTが冪等でないために発生します。この問題を防ぐための最も一般的な設計パターンがPRGパターン (Post/Redirect/Get) です。
- Post: クライアントはフォームデータをPOSTリクエストでサーバーに送信します。
- Redirect: サーバーはPOSTリクエストの処理が成功した後、レスポンスとしてHTTPステータスコード303 See Other(または302 Foundなど)と共に、結果を表示する別のURLを
Location
ヘッダーでクライアントに返します。 - Get: クライアントはLocationヘッダーで指定されたURLに対してGETリクエストを自動的に送信します。
このパターンにより、ユーザーがGETリクエストで表示された結果ページをリロードしても、再送信されるのは安全かつ冪等なGETリクエストなので、サーバーの状態が意図せず変更されることはありません。二重送信のリスクを効果的に回避できます。
7.4 GETリクエストのボディにデータを含めることの非推奨性
GETメソッドはクエリパラメータを使ってデータを渡すのが標準的な方法ですが、技術的にはGETリクエストにリクエストボディを含めることも可能です。しかし、これはHTTPの仕様(RFC 7231 section 4.3.1)で明確に非推奨 (SHOULD NOT) とされています。
非推奨とされる主な理由:
- 意味論の不一致: GETは「取得」であり、サーバーにデータを渡して処理させる「送信」や「操作」とは目的が異なります。
- 互換性の問題: 多くのサーバー、プロキシ、ファイアウォール、キャッシュシステムは、GETリクエストにボディが含まれていることを想定しておらず、ボディを無視したり、リクエストをブロックしたり、予期しない挙動を引き起こしたりする可能性があります。特に、プロキシはキャッシュキーを生成する際にボディを考慮しないことが一般的で、キャッシュの挙動がおかしくなる原因となります。
- ブラウザのサポート: ほとんどのWebブラウザは、ユーザー操作(リンククリック、アドレスバー入力など)によるGETリクエストにリクエストボディを含める機能をサポートしていません。JavaScriptでFetch APIなどを使えばボディを含めることは可能ですが、非推奨であることに変わりはありません。
したがって、GETリクエストにはリクエストボディを含めるべきではありません。サーバーにデータを渡して処理させたい場合は、クエリパラメータを使うか、POST
などの他のメソッドを使うべきです。
7.5 PUT vs POST (更新の場合)
GETとPOSTに加えて、リソースの更新に関連するPUT
メソッドについても、POSTとの違いを明確にしておきましょう。
- PUT /resources/{id}:
PUT
は、指定されたURI{id}
のリソースを、リクエストボディに含まれるデータで完全に置き換えるためのメソッドです。クライアントはリソースの新しい完全な状態をサーバーに送信します。URIで指定されたリソースが既に存在する場合は更新、存在しない場合は新規作成(ただし、PUTは「作成」より「指定されたURIにリソースを配置する」という意味合いが強い)となります。冪等性があります。 同じPUTリクエストを何度実行しても、リソースの状態は常にリクエストボディで指定された状態になります。 - POST /resources/{id} または POST /resources:
POST
は、指定されたリソース(またはリソースのコレクション)に対して、リクエストボディのデータを用いて何かをするためのメソッドです。新しいリソースの作成が典型的ですが、既存リソースの一部更新や、リソースに関連するアクション実行にも使われます。通常、冪等性はありません。 同じPOSTリクエストを複数回実行すると、結果が異なる可能性があります。
例えば、ユーザーID=123のユーザー情報を更新する場合:
PUT /users/123
(リクエストボディにユーザー123の新しい完全な情報)
これは、ユーザー123の情報をリクエストボディの内容で丸ごと置き換えます。POST /users/123
(リクエストボディにユーザー123の変更したいフィールドのみ、あるいは何らかの更新指示)
これは、ユーザー123に対してリクエストボディの内容で何らかの処理を行います。例えば、プロフィールの一部の変更、パスワードの変更、ステータスの変更など、POSTの処理内容はURIとボディの内容次第で柔軟に定義できます。しかし、この柔軟性が「冪等性がない」という性質に繋がります。
RESTfulな観点では、リソース全体を置き換える明確な更新操作にはPUT
を、新しいリソースの作成や、リソースに対する非冪等なアクションにはPOST
を使い分けるのが理想的です。ただし、実際のAPIでは、既存のリソースの更新にもPOSTが広く使われているという現状もあります。
8. まとめ:賢い使い分けがAPI設計の鍵
本記事では、API通信の根幹をなすHTTPメソッドの中から、GET
とPOST
に焦点を当てて、その違いと使い分けを詳細に解説しました。
- GETメソッドは「取得」のため。 安全で冪等であり、リソースの状態を変更しません。データはクエリパラメータで渡し、キャッシュが可能、ブラウザから容易にアクセスできるといった特徴があります。情報の参照や検索など、サーバーからデータを「読み取る」場合に利用します。
- POSTメソッドは「送信と操作」のため。 安全でも冪等でもなく、リソースの作成や更新など、サーバーの状態を変更する可能性があります。データはリクエストボディで渡し、大量のデータや機密情報を送るのに適しています。新しいリソースの作成、既存リソースの更新、フォーム送信、ファイルアップロード、特定のアクション実行など、サーバーにデータを渡して「処理をしてもらう」場合に利用します。
これらのメソッドの核となる違い(目的、安全性、冪等性、データの送信方法)を理解することは、APIを正しく利用するクライアント側にとっても、適切で堅牢なAPIを設計するサーバー側にとっても、非常に重要です。
誤ったメソッドの使用は、セキュリティ上の問題(GETで機密情報送信、状態変更操作)、予期しない挙動(POSTリロードによる二重送信)、キャッシュの問題、インフラストラクチャとの非互換性などを引き起こす可能性があります。
API設計においては、実現したい操作の性質を明確にし、「これはリソースの取得か?それともサーバーの状態を変更する操作か?」という問いを立てて、適切なHTTPメソッドを選択するように心がけましょう。また、RESTfulな原則に沿った設計を意識することで、APIの分かりやすさ、使いやすさ、保守性が向上します。
GETとPOSTはHTTPメソッドのほんの一部に過ぎませんが、これら二つを正しく理解することが、他のHTTPメソッドやより複雑なAPI設計パターンを学ぶ上での確固たる基盤となります。本記事が、皆様のAPI開発や利用における一助となれば幸いです。
この知識を活かして、安全で効率的、そして意図が明確なAPIを構築・利用していきましょう!