HTTP POSTリクエスト徹底解説:仕様から実務・セキュリティ・ベストプラクティスまで

はじめに

Web開発やAPI設計の現場で最も頻繁に使われるHTTPメソッドの一つが「POST」です。本稿では「POSTリクエストとは何か」を技術的に深掘りし、仕様上の位置づけ、ブラウザやサーバーでの扱い、代表的なヘッダーやボディ形式、セキュリティ・運用上の注意点、実務でのベストプラクティスまでを詳しく解説します。開発者が日常的に使う機能ですが、正しく理解していないとバグや脆弱性、パフォーマンス問題につながるため、RFCや主要ドキュメントに基づいて丁寧に説明します。

POSTリクエストの定義(HTTP仕様における位置づけ)

POSTはHTTP/1.1のメソッドの一つで、RFC 7231(Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content)で定義されています。POSTの基本的な目的は、リソースに対する「データの提出」や「サーバー側での処理の起動」です。具体的には、サーバー側で新しい子リソースを作成したり、フォームデータを送って処理を実行したりする用途に使われます。

重要な仕様上のポイントは次の通りです:

  • POSTは通常「非冪等(非idempotent)」であり、同じPOSTを複数回送ると副作用が重複する可能性がある(RFC 7231)。ただし設計次第で冪等に扱うことも可能。
  • POSTは「安全(safe)」ではない:状態を変更する可能性があるためGETのように副作用がないとは限らない。
  • レスポンスの意味は用途に依存する。たとえばリソース作成なら201 Created、非同期処理の受け付けなら202 Acceptedなどが使われる。

GETとの主な違い

しばしば混同されるGETとPOSTですが、用途や動作に違いがあります。

  • 目的:GETはリソースの「取得(安全で副作用がないことが期待される)」、POSTは「データの送信・処理の指示」。
  • ボディ:GETはリクエストボディを送ることが仕様上許される場合もあるが、現実の実装(ブラウザ・プロキシなど)では無視されることが多く、実務ではGETにボディを使わないのが一般的。一方、POSTはリクエストボディにデータを入れる設計。
  • キャッシュ:GETのレスポンスはキャッシュされやすいが、POSTのレスポンスは特に明示的なキャッシュ指示がない限りキャッシュされない(RFC 7234)。
  • ブックマークや共有:GETのURLはそのままブックマークできるが、POSTはボディを含むため容易にはブックマークできない。

POSTの主な用途

  • リソースの作成(例:ユーザー登録、記事投稿)。かつては「子リソースを作る」ことが多い。
  • サーバー側での何らかの処理を指示(例:ファイルのアップロード、フォーム送信、メール送信、検索クエリ送信など)。
  • 非同期処理のキックオフ(処理を受け付けてジョブIDを返し、別エンドポイントで進捗確認)。

リクエストボディと代表的なContent-Type

POSTで送るデータはContent-Typeヘッダーで形を定義します。代表的なもの:

  • application/x-www-form-urlencoded:HTMLフォームのデフォルト。キー=値のURLエンコード形式。
  • multipart/form-data:ファイルアップロードや複合パートを扱うときに使用。各パートごとにContent-Disposition等が付く。
  • application/json:APIで一般的。JSON文字列をそのままボディに置く。
  • text/plainやapplication/xmlなど:用途に応じて任意のMIMEタイプを使う。

Content-Length(またはTransfer-Encoding: chunked)で長さ・分割送信を示します。大きなアップロード時はチャンク転送(chunked)やストリーミング処理が使われます。

ブラウザとHTMLフォームの振る舞い

HTMLフォームではmethod属性にPOSTを指定すると、ブラウザはフォームのname/valueをボディにエンコードして送信します。enctype属性でエンコード方式を選びます(例:multipart/form-dataはファイルを含める際に必須)。ファイル選択でのアップロードは基本的にmultipart/form-dataです。

なお、ブラウザではCORSポリシーに基づく制約があるため、POSTでもContent-Typeやカスタムヘッダーの種類によってはプリフライト(OPTIONS)リクエストが発生します。特にapplication/jsonや独自ヘッダーは"simple"なリクエスト条件を満たさないためプリフライトが行われます。

典型的なレスポンスとステータスコード

POSTに対するレスポンスは操作に応じて適切なHTTPステータスを返すべきです。よく使われるもの:

  • 201 Created:リソースを作成した場合。Locationヘッダーで新規リソースのURIを通知するのが推奨。
  • 200 OK:リクエストが成功し、結果を返す場合(作成ではなく処理結果の返却など)。
  • 202 Accepted:リクエストは受理したが処理は非同期で未完了の場合。
  • 204 No Content:成功したが返す本文がない場合。
  • 3xx(リダイレクト):POSTに対しては303 See Otherや307/308など、リダイレクト挙動を明確にするステータスが使われる。ブラウザは303でGETに切り替える等の挙動を行う。
  • 4xx/5xx:バリデーションエラー、認証/認可エラー、サーバーエラーなど。

冪等性と再試行の扱い

POSTは原則として非冪等です。つまり同一のPOSTを複数回送ると複数の副作用が発生する可能性があります。これに対処するため、API設計では「冪等性キー(idempotency key)」を導入して重複リクエストをサーバー側で検出・合体する手法がよく使われます(支払いAPIなど)。

一方、PUTは一般に冪等であり、同じPUTを何度行っても結果が同じになるように設計されます。したがって「既知の識別子で上書きする」操作はPUTを使い、新規作成やサーバーに作成ロジックを委ねる操作はPOSTが適切、というのがREST的なガイドラインです。

キャッシュ、プロキシ、ヘッダーの扱い

POSTレスポンスはデフォルトでキャッシュされにくいですが、Cache-ControlやExpires、ETagなどのヘッダーを明示すればキャッシュ可能です。プロキシや中間機器はGET/HEADに比べてPOSTのボディを扱う際に挙動が差異になることがあるため、プロキシ越しの大容量送信や特殊なContent-Typeを使用する際は注意が必要です。

セキュリティ上の注意点

  • CSRF(クロスサイトリクエストフォージェリ):POSTは状態を変更することが多いため、CSRFトークンやSameSite Cookie、Originヘッダーの検証などで保護する必要があります(OWASP推奨)。
  • HTTPSの必須:機密情報(パスワード、トークン、個人情報)を送る場合は必ずTLSで暗号化されたチャネルを使用します。
  • 認証・認可:Authorizationヘッダーやセッションクッキーの管理。POSTでも適切な認可チェックを行うこと。
  • 入力検証と出力のサニタイズ:SQLインジェクションやコマンドインジェクション、XSSにつながらないようサーバー側で厳格にバリデーションする。

CORS(クロスオリジン)とプリフライト

ブラウザから別オリジンへPOSTする場合、Content-Typeがapplication/x-www-form-urlencoded、multipart/form-data、text/plainのいずれかでカスタムヘッダーが無ければ「シンプルリクエスト」としてプリフライトが不要です。しかしapplication/jsonを送る、あるいは独自ヘッダーを付ける場合はOPTIONSによるプリフライトが行われ、サーバー側でAccess-Control-Allow-*ヘッダーを返す必要があります。

大容量データ・ストリーミング・実装上の注意

  • 大容量ファイルをPOSTで送信する場合、サーバーのタイムアウトや最大ボディサイズ、ストリーミング対応(ストリーム処理、チャンク処理)を考慮する。
  • Expect: 100-continueヘッダーでクライアントは先にヘッダーを送り、サーバーの応答(100 Continue)を待ってから大きなボディを送信することで無駄なアップロードを防げる。サーバーが対応していないこともあるので実装注意。
  • 再送やタイムアウト時の重複処理を避けるため、クライアント側で冪等性キーを付与する、サーバー側で重複チェックを行うなどの対策が有効。

実務でのベストプラクティス

  • 意味に合ったメソッドを選ぶ:取得はGET、既知IDの上書きはPUT、新規作成や処理実行はPOST。
  • レスポンスステータスとLocationヘッダーを正しく使う:作成時は201 + Location。
  • POST後のブラウザでの再読み込み問題にはPRGパターン(Post/Redirect/Get)を採用して「再送信の確認」を回避する。
  • CSRF対策、HTTPS、入力バリデーション、サイズ制限を徹底する。
  • APIでは冪等性キーやトランザクションIDで重複処理を防止する。
  • ドキュメント化:送受信するContent-Type、必須フィールド、想定されるステータスコードをAPI仕様書に明記する。

まとめ

POSTは「データをサーバーに送って処理させる」ための汎用的なHTTPメソッドであり、フォーム送信やファイルアップロード、リソース作成や非同期処理開始など幅広く使われます。仕様上は非冪等であり安全ではないため、セキュリティや再試行の扱い、適切なステータスコードやヘッダーの運用が重要です。現場では冪等性キーやPRG、厳格な入力検証、CORS/CSRF対策、TLSの徹底などを組み合わせて安全かつ信頼性の高いPOST処理を実装してください。

参考文献