動画で読む
まず結論 — QUERY は「安全で冪等な検索」を HTTP に正式に持ち込む
結論から書きます。2026 年に IETF が RFC 10008 として標準化した HTTP QUERY メソッドは、「検索のように body でパラメータを渡したいが、副作用は無いと明示したい」という長年の隙間を埋めるものです。QUERY は GET と同じく安全(safe、サーバの状態を変えない)かつ冪等(idempotent、何度送っても同じ)で、しかも POST のようにリクエスト body を持てます。
これまで複雑な検索条件を投げたい開発者は、二択を迫られていました。GET の URL に全部詰め込むか、POST で投げて「これは安全な検索です」という意味論を諦めるか。私も自分の API 一覧に POST /search を何十個も並べてきた側の人間です。QUERY はその二択そのものを無くす提案で、運用者として読む価値があると判断しました。
なぜ GET-with-body と POST /search では足りなかったのか
足りなかった理由は単純で、GET に body を付ける手は仕様上ほぼ未定義で危険、POST で検索する手は意味論の嘘を含むからです。どちらも「動くけれど正しくない」状態でした。
GET に body を付ける案は、HTTP の仕様上「body の意味は定義されない」とされていて、途中のプロキシや CDN が body を捨てたり無視したりします。実際に試した人が一様に「環境依存で信用できない」と言うのはこのためです。一方の URL 詰め込みは、条件が増えると簡単に限界に当たります。私は以前、検索条件を全部クエリ文字列に載せたら 414 URI Too Long をプロキシ側で踏んだことがありました。さらに厄介なのは、URL は各所のアクセスログに丸ごと残るので、検索語に個人情報が混ざると意図せずログへ漏れる点です。
では POST はどうか。動きはします。でも POST /search という名前は、副作用が無いはずの検索に「何かを作る」という顔をさせている小さな嘘です。キャッシュは効かないと見なされ、ネットワークの途中で安全に再試行することもできません。安全で冪等という性質を、実装の都合で捨てているわけです。LLM の API でも「呼ばないこと」が最大のコスト防御だとLLM API コストの三段防御で書きましたが、そもそも安全な読み取りをキャッシュできない形で投げているなら、その防御の土台が崩れます。
QUERY の中身 — 安全・冪等・body 必須・キャッシュ可能
QUERY の核は四つです。安全であること、冪等であること、リクエスト body と Content-Type が必須であること、そしてレスポンスがキャッシュ可能であること。GET の意味論に body の表現力を足した、と読むと腹落ちします。
RFC 10008 は QUERY を「対象リソースに対して安全であり、クライアントは状態の変更を要求も期待もしない」と定義します。同時に「QUERY は冪等であり、必要なら再送・反復できる」とも書かれている。つまり途中の経路が安全に retry してよい読み取りだと、メソッド名だけで宣言できます。入力は URI ではなく「リクエストの内容(content)として渡す」ので、ネストした検索条件や長い構造体も素直に表現できます。
ひとつ実装で効いてくるのが Content-Type の扱いです。仕様は「Content-Type ヘッダが欠けているか、内容と矛盾している場合、サーバは MUST でリクエストを失敗させる」と定めています。body が JSON なのか何なのかを曖昧にできない、という地味だが重要な縛りです。リダイレクトの挙動も整理されていて、301 / 302 / 307 / 308 では body を付け直して再送、303(See Other)なら「同じ結果を GET で取れる別 URI」を案内する、と用途が分かれています。条件付きリクエスト(If-Modified-Since など)も GET と同じように使えます。
キャッシュが一番の論点 — cache key に body が入る
運用者として一番注意すべきは、QUERY のレスポンスはキャッシュできるが、そのキャッシュキーにリクエスト body 全体が含まれる点です。GET の「URL がそのままキー」という気軽さは、ここでは通用しません。
RFC は「QUERY のキャッシュキーはリクエストの内容と関連メタデータを取り込まなければならない(MUST)」と書いています。これは GET より明らかに重い処理です。キャッシュのヒット判定のために、毎回 body を最後まで読んでハッシュ化する必要があるからです。CDN や手前のリバースプロキシが QUERY を素通しするだけだと、キャッシュは一切効きません。プロキシ層が QUERY を理解して body ベースのキーを組めるまでは、実利用でキャッシュ恩恵を受けるのは当面むずかしい、と私は見ています。プロキシ層の設計がアプリの性能を左右するという話はPgDog で Postgres を透過シャーディングするでも書いたとおりで、QUERY もまさに中間層の対応待ちです。
もうひとつ便利なのが Content-Location です。サーバは 2xx レスポンスにこのヘッダを付けて「この検索結果に対応するリソースの URI」を返せます。クライアントはその URI を普通の GET で取り直せるので、QUERY で一度問い合わせて結果を URL 化し、以降は GET でキャッシュに乗せる、という二段構えが組めます。検索のたびにサーバ往復を体感へ漏らさない発想は、Linear の同期エンジンで読んだ「ネットワークを待たない」設計と通じるものがあります。
運用者として、いつ QUERY に乗り換えるか
私の現実的な線引きはこうです。新規の複雑な検索エンドポイントを設計するときは QUERY を第一候補に置く。一方で、既存の POST /search を急いで置き換える理由は、まだ薄い。クライアントとプロキシの両対応が揃ってから、というのが 2026 年時点の正直な距離感です。
理由は対応状況にあります。サーバ側は Rails でも素のミドルウェアでも、メソッドを受けて body をパースするだけなので難しくありません。問題はその先で、ブラウザの fetch や各言語の HTTP クライアント、そして CDN・プロキシが QUERY を一級市民として扱うまでには時間がかかります。未対応の経路に当たると、せっかくの安全・冪等・キャッシュ可能という性質が宝の持ち腐れになる。だから当面は、内部 API や自分で経路を握れる箇所から試すのが安全です。
それでも私はこの RFC を歓迎しています。POST /search というささやかな嘘を、HTTP がやっと正面から引き受けてくれたからです。安全な読み取りを安全だと名乗れる。その当たり前が標準化されたことに、長く API を書いてきた身としては小さく拍手したい気分です。乗り換えは急がない。でも次に検索エンドポイントを新設するとき、私はまず QUERY が使えるかを確かめるはずです。
よくある質問
- HTTP QUERY メソッドは安全 (safe) で冪等 (idempotent) ですか?
- はい。RFC 10008 は QUERY を GET と同様に安全かつ冪等と定義しています。サーバの状態を変えず、何度再送しても結果が変わらないため、途中の経路が安全に再試行できます。GET との違いはリクエスト body を持てる点です。
- GET に body を付ける方法ではなぜダメなのですか?
- HTTP 仕様では GET の body の意味が定義されておらず、プロキシや CDN が body を捨てたり無視したりするため信頼できません。条件を URL に詰めると 414 URI Too Long に当たり、検索語がアクセスログに残る問題もあります。
- QUERY のレスポンスはキャッシュできますか?
- できますが、キャッシュキーにリクエスト body 全体を含める必要があります(RFC は MUST と規定)。GET のように URL だけをキーにできないため、CDN やプロキシが QUERY を理解して body ベースのキーを組めることが前提になります。
- 既存の POST /search をすぐ QUERY に置き換えるべきですか?
- 急ぐ必要はありません。サーバ実装は容易ですが、ブラウザ fetch・各言語の HTTP クライアント・CDN・プロキシの対応が揃うまで恩恵が限られます。新規の検索エンドポイントや経路を自分で握れる内部 API から試すのが現実的です。