HTTPQUERY
日本語

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 は新しいリソースの作成やサーバー側の処理の起動のためのものです。