POST
使い方
POST リクエストは、指定されたリソースにエンティティを送信します。サーバーは、そのリソース自身のセマンティクスに基づいて、同梱された表現をどう扱うかを決定します。特定のリソース URI を対象とする PUT とは異なり、POST はターゲット URI で識別されるリソースに処理を委ねます。
Content-Type ヘッダーはリクエストボディの形式を示します。HTML フォームと API では3つのエンコーディングが一般的です。
application/x-www-form-urlencoded
HTML フォームのデフォルトのエンコーディングです。データはアンパサンド(&)で区切られたキーと値のペアとして構成され、キーと値はイコール記号(=)で結ばれます。英数字以外の文字はパーセントエンコーディングを使用します。
name=Alice&role=admin
multipart/form-data
各フィールドは、Content-Type ヘッダーで宣言された境界文字列で区切られた別々のパートを占めます。このエンコーディングはファイルアップロードなどのバイナリデータをサポートします。各パート内の Content-Disposition ヘッダーがフィールド名を示します。
text/plain
規定された構造はありません。サーバーは独自のロジックに従って生のボディを処理します。
POST リクエストの繰り返しは冪等ではありません。同じフォームを2回送信すると、2つのリソースが作成されるか処理が2回発生します。これは、繰り返しても同じサーバー状態になる PUT とは異なります。
POST のレスポンスは、明示的な鮮度情報と対応する Content-Location ヘッダーが含まれる場合にのみキャッシュ可能です。
フォーム送信
クライアントが URL エンコード形式を使ってフォームデータを送信します。サーバーはジョブを作成し、201 Created で応答します。
リクエスト
POST /jobs HTTP/1.1
Host: api.example.re
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
name=backup&pri=2
レスポンス
HTTP/1.1 201 Created
Location: /jobs/47
Content-Type: application/json
Content-Length: 38
{"id":47,"name":"backup","priority":2}
マルチパートのファイルアップロード
クライアントがマルチパートエンコーディングを使ってファイルをアップロードします。境界文字列 ----Boundary が各パートを区切ります。サーバーはアップロードを受け付け、202 Accepted を返します。
リクエスト
POST /uploads HTTP/1.1
Host: api.example.re
Content-Type: multipart/form-data; boundary=----Boundary
Content-Length: 196
------Boundary
Content-Disposition: form-data; name="title"
Q4 Report
------Boundary
Content-Disposition: form-data; name="file"; filename="report.pdf"
Content-Type: application/pdf
<binary data>
------Boundary--
レスポンス
HTTP/1.1 202 Accepted
Location: /uploads/91
Content-Length: 0
JSON API
クライアントが新しいユーザーを作成するために JSON ペイロードを送信します。サーバーは id フィールドを伴う作成済みリソースを返します。
リクエスト
POST /users HTTP/1.1
Host: api.example.re
Content-Type: application/json
Content-Length: 41
{"email":"alice@example.re","role":"ops"}
レスポンス
HTTP/1.1 201 Created
Content-Type: application/json
Content-Length: 50
{"id":112,"email":"alice@example.re","role":"ops"}
CORS
POST は CORS セーフリストメソッドですが、それは Content-Type が application/x-www-form-urlencoded、multipart/form-data、text/plain のいずれかである場合に限られます。application/json やその他のコンテンツタイプを伴う POST は、プリフライトの OPTIONS リクエストを発生させます。
POST と GET の比較
POST はデータを URL ではなくリクエストボディで運びます。これによりパラメーターがブラウザの履歴、サーバーログ、Referer ヘッダーに残らないため、POST は機微なデータにより適しています。
POST のレスポンスはデフォルトではキャッシュされず、ブックマークもできません。POST は安全でも冪等でもないため、送信を繰り返すと重複したリソースが作成されたり、処理が複数回発生したりします。
POST には実用上のボディサイズ制限がありませんが、GET は 2048 文字前後の URL 長の制限に縛られます。
SameSite=Lax のクッキーはクロスサイトの POST リクエストをブロックしますが、クロスサイトの GET は許可します。これにより POST には、GET にはない一定の CSRF 保護が組み込まれています。
セキュリティ
POST のデータは URL、ブラウザの履歴、Referer ヘッダーには現れません。これにより、GET と比べて偶発的なデータ露出のリスクが低減します。
それでも POST は、適切なトークンがなければ CSRF 攻撃に対して脆弱です。悪意のあるページ上のフォームは、他のオリジンへ自動的に POST リクエストを送信します。SameSite=Lax のクッキーはクロスサイトでの POST クッキー送信をブロックすることで部分的な保護を提供しますが、専用の CSRF トークンは依然として必要です。
平文の HTTP 上の POST はデータをクリアテキストで送信します。転送中のリクエストボディを保護するには HTTPS が必要です。
POST と PATCH の比較
POST はサーバーが選んだ URI に新しいリソースを作成します。PATCH は既知の URI にある既存のリソースを変更します。
POST は処理のセマンティクスを完全にサーバーに委ねます。PATCH には、適用すべき具体的な変更を記述する JSON Patch や JSON Merge Patch といった定義済みのパッチ形式があります。
クライアントが既存のリソースの特定のフィールドを更新する必要がある場合は、PATCH が適切なメソッドです。POST は新しいリソースの作成やサーバー側の処理の起動のためのものです。