3秒でわかる
サーバーが本文と一緒に返す付帯情報。中身の種類や文字コード、キャッシュの扱いや権限の指示を、本文とは別枠で伝えるために使います。
30秒図解
もう少し詳しく
どういうものか
レスポンスヘッダーは、HTTP の応答で本文の前に付いてくるキーと値の並びです。本文そのものではなく、本文をどう扱えばよいかをブラウザに指示します。中身の種類を表す Content-Type、保存期間を決める Cache-Control、クッキーを渡す Set-Cookie、別の場所へ送る Location などが代表格です。
ブラウザの開発者ツールのネットワークタブで、リクエストを選ぶと一覧で確認できます。
なぜ必要か
同じバイト列でも、HTML として描画するのか、ファイルとしてダウンロードさせるのか、画像として表示するのかは中身だけでは決まりません。ヘッダーで種類を伝えることで、受け取る側は正しい扱いを選べます。
キャッシュや安全性の制御もヘッダーが担います。何秒間再取得しなくてよいか、別のサイトから読み込んでよいか、フレームに埋め込んでよいか、といった指示は本文に書けません。本文と分けておくことで、ブラウザは本文を読む前に判断できます。
具体例
curl -I https://example.comHTTP/2 200
content-type: text/html; charset=UTF-8
content-length: 1256
cache-control: public, max-age=3600
etag: "a1b2c3d4"
set-cookie: session=abc123; HttpOnly; Secure; SameSite=Lax
x-content-type-options: nosniff// Node.js で返す側を書く
res.writeHead(200, {
"Content-Type": "application/json; charset=utf-8",
"Cache-Control": "no-store",
"Access-Control-Allow-Origin": "https://app.example.com",
});
res.end(JSON.stringify({ ok: true }));
// 受け取る側で読む
const res = await fetch("/api/items");
console.log(res.headers.get("content-type"));
console.log(res.headers.get("x-total-count"));つまずきやすいところ
JSON を返しているつもりなのに Content-Type が text/plain のままだと、受け取り側のライブラリがパースを拒むことがあります。文字コードを付け忘れると日本語が化けるので、charset=utf-8 まで含めて指定します。
Cache-Control の指定漏れも定番です。指定が無いとブラウザや中間のキャッシュが独自の判断で保持し、更新したはずの JSON が古いまま返り続けます。API なら no-store、変わらない静的ファイルなら長い max-age と、性質で分けます。
fetch から独自ヘッダーを読もうとして null が返る、という詰まり方もよくあります。クロスオリジンの応答では、既定でごく一部のヘッダーしか JavaScript に見えません。サーバー側で Access-Control-Expose-Headers に名前を並べる必要があります。
ヘッダーは本文より先に送られるため、本文を書き始めた後に追加しようとするとエラーになります。
似た用語との違い
| 語 | 向き |
|---|---|
| レスポンスヘッダー | サーバーからクライアントへの付帯情報 |
| リクエストヘッダー | クライアントからサーバーへの付帯情報 |
| ステータスコード | 応答の結果を数字で表す。200 や 404 |
| ボディ | 実際のデータ本体。HTML や JSON |