ファイルの大きさや更新情報だけを知りたいとき、本文を全部ダウンロードする必要はあるでしょうか。HTTPのHEADメソッドは、同じ要求をGETで送った場合の応答に対応するメタデータを、本文を受け取らずに調べるための方法です。
ただし「本文が届かない」「ファイルが空」「サーバーが軽い処理だけで返した」は、それぞれ別です。HEADの応答を読むときは、実際に受信した本文の長さと、ヘッダーが説明している対象を分けます。
簡単にまとめると?
- HEADでは応答本文を送りません。Content-Lengthがあれば、それは同じ要求をGETにした場合の本文のバイト数を示します。
- 本文を生成しないと分からないヘッダーは、省略できる場合があります。HEADだけで完全な本文検査やサーバー負荷の評価はできません。
- 保存済みGET応答の更新には、ETagなどの検証子やContent-Lengthの照合が関わります。HEADが200だったことだけで、古い本文を最新版と決めません。
Content-Lengthが大きくても、本文は来ない
例えば、同じ条件のGETで1,048,576バイトのデータを返す資源を考えます。HEADの応答が200 OKで、Content-Length: 1048576を含んでいても、その後に同じ量の本文が続くわけではありません。HEADでは応答本文を送らない、というメソッドの意味が先にあります。[1、9.3.2節]
HEADでContent-Lengthを送る場合、その値は同じ要求をGETに変えたときに送る本文のバイト数と一致しなければなりません。[1、8.6節] 「HEADで受け取った本文が0バイトだから、Content-Lengthも0に直す」と処理すると、資源の説明を変えてしまいます。
ここでいう「同じ条件」も大切です。認証やコンテンツ選択に関わる要求ヘッダーが違えば、同じURLでも選ばれる表現が違うことがあります。圧縮を指定した応答と、圧縮しない応答を混ぜてサイズを比較するのも避けます。URLだけでなく、何を要求したかを一緒に記録します。
省けた転送量と、サーバーの仕事量は分ける
以下は、説明用のローカルHTTPサーバーへHEADとGETを送った確認です。サーバーは1,048,576バイトの固定データを持ち、両方に同じContent-LengthとETagを返すよう実装しました。HEADでは本文を書き込まず、GETでは全体を書き込んでいます。

この試験では本文の転送を省けますが、任意のWebサービスが同じように計算量まで省けることを示してはいません。実装によっては、返す値を調べるためにデータベースへ問い合わせたり、生成処理の一部を行ったりします。逆に、保存済みのサイズや更新情報だけで答えられる場合もあります。応答本文が0バイトという観測から、内部処理時間を推定することはできません。
仕様も、GETとHEADでヘッダーが一字一句同じになることを常に求めてはいません。本文生成中にしか値が決まらない項目は、HEADで省略できる場合があります。動的応答のContent-LengthやVaryが例として挙げられています。[1、9.3.2節] Content-Lengthがなかったからといって、内容が0バイトだと判断しないことが重要です。
保存した本文を再利用するなら、何と照合するか
HEADの200応答は、保存済みGET応答のメタデータを更新する材料にもなります。RFC 9111は、対象となる保存応答について、受信したETagやLast-Modifiedの値が一致し、HEADにContent-Lengthがあればその長さも一致するとき、保存情報を更新する手順を示しています。条件が合わなければ、保存応答をstale、つまり鮮度が失われた状態として扱うことを推奨します。[2、4.3.5節]
例えば保存本文が版aで、HEADもETagが版a、長さも一致していれば、その応答を更新する判断材料が揃います。一方、HEADのETagが版bに変わっていたら、200 OKだからといって版aの本文を版bとして扱うことはできません。HEADは新しい本文を運んでいないからです。
長さが同じことだけを、内容の一致の証明にもしません。「abc」と「xyz」はともに3バイトですが、内容は違います。正しい検証子の運用と、選択対象の照合が必要です。また、ヘッダー更新の手順はキャッシュの規則であって、アプリケーションが独自に保持するファイルを無条件に書き換えてよい、という意味ではありません。
HEADと条件付きGETを使い分ける
知りたいのがメタデータだけで、変わっていても今は本文を取りたくないなら、HEADが用途に合います。すでに本文と検証子を持ち、「変わっていなければ本文なし、変わっていたら新しい本文が欲しい」なら、条件付きGETも候補になります。RFC 9111も、保存済み応答に検証子がない場合や、変更時にも本文転送を望まない場合のHEAD利用を説明しています。[2、4.3.5節]
HEADを先に送った後でGETする構成では、二つの要求の間に内容が変わる可能性もあります。先のHEADのサイズと後のGETの本文が一致しないとき、直ちに転送破損と決めず、返された版や選択条件を照合します。事前確認と実際の取得を、一つの原子的な操作とは扱わないためです。
リンクの応答状況を軽く調べる目的と、本文が読めるか、画像が表示されるか、内容が期待どおりかを確かめる目的も分けます。HEADの成功は後者の検査を代行しません。受信本文を省きながら何を知るのかを先に決めると、必要なヘッダーと、別途GETで確かめる範囲が明確になります。
出典
- RFC 9110: HTTP Semantics(2022年6月、STD 97)、9.3.2節HEAD、8.6節Content-Length。
- RFC 9111: HTTP Caching(2022年6月、STD 98)、4.3.5節Freshening Responses with HEAD。
