ヘッダーは「一緒にくっついて飛んでいくメモ書き」
まずイメージからいきます。
HTTP の世界では、リクエストやレスポンスは「封筒付きの手紙」みたいなものです。
本文(ボディ)
実際の中身。JSON や HTML、テキストなど。
ヘッダー(Headers)
「これはこういう形式ですよ」「こういう条件でお願いします」といったメモ書き。
この「メモ書き」の部分を、JavaScript から扱うための仕組みが Headers オブジェクト です。fetch で通信するとき、ほぼ必ずヘッダーを意識することになります。
Headers オブジェクトって何者か
「キーと値のセット」を扱うための専用クラス
Headers は、ざっくり言うと「文字列のキーと値のセット」を扱うためのオブジェクトです。
例えば、こんな情報を持ちます。
Content-Type: application/json
Authorization: Bearer xxx
Accept: application/json
JavaScript からは、Headers クラスとして扱えます。
const headers = new Headers();
headers.set("Content-Type", "application/json");
headers.set("X-Custom-Header", "hello");
JavaScriptでも、ふだんは fetch のオプションで素直にオブジェクトを書くだけで十分です。
fetch("/api", {
headers: {
"Content-Type": "application/json",
"X-Custom-Header": "hello",
},
});
JavaScriptこのオブジェクトは内部で Headers に変換されます。
「Headers というクラスがある」と知っておけば、まずは OK です。
大事なのは「何を書くか」であって「どう書くか」ではない
初心者のうちは、new Headers() を直接触るよりも、
どんなヘッダーを付けるべきか
そのヘッダーは何を意味しているのか
を理解するほうが圧倒的に重要です。
なので、このあと「よく使うヘッダー」と「それが何を伝えているか」にフォーカスして話します。
Content-Type は「この中身は何形式か」を伝える
JSON を送るときの定番ヘッダー
一番よく見るのがこれです。
headers: {
"Content-Type": "application/json",
}
JavaScriptこれは、
「このリクエストのボディは JSON ですよ」
とサーバーに教えるためのヘッダーです。
例えば、ユーザー情報を JSON で送るとします。
const user = { name: "taro", age: 20 };
await fetch("/api/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(user),
});
JavaScriptここでやっていることは、
ボディを JSON 文字列にする(JSON.stringify)
その形式を Content-Type: application/json で宣言する
というセットです。
サーバー側はこのヘッダーを見て、
「じゃあ JSON としてパースしよう」と判断します。
Content-Type を間違えるとどうなるか
例えば、ボディは JSON なのに Content-Type を付け忘れると、
サーバー側が「これは何の形式だ?」と迷います。
サーバーの実装によっては、
ボディを無視する
エラーにする
変な形で解釈してしまう
などの問題が起きます。
逆に、Content-Type だけ application/json にしておいて、
ボディが JSON になっていないと、
サーバー側でパースエラーになります。
つまり、
「ボディの中身」と「Content-Type」は必ずセットで考える
これがとても大事なポイントです。
Accept は「こういう形式で返してほしい」を伝える
クライアント側の希望を伝えるヘッダー
Accept ヘッダーは、
「レスポンスはこういう形式で返してくれると嬉しいです」という希望をサーバーに伝えます。
例えば、JSON が欲しいときはこう書きます。
await fetch("/api/user", {
headers: {
Accept: "application/json",
},
});
JavaScriptサーバー側はこれを見て、
「じゃあ JSON で返そう」と判断することが多いです。
もちろん、サーバーがそれに対応していない場合もありますが、
「クライアントの希望を伝える」という意味で重要なヘッダーです。
Content-Type と Accept の違い
ここを混同しがちなので、整理しておきます。
Content-Type
「送る側のボディの形式」
リクエストなら「このリクエストボディは JSON です」
レスポンスなら「このレスポンスボディは HTML です」など
Accept
「受け取りたいレスポンスの形式」
「JSON で返してくれると嬉しいです」など
つまり、
送るときの形式 → Content-Type
欲しい返事の形式 → Accept
という役割分担です。
Authorization は「誰なのか」を伝える
認証・認可に関わる重要ヘッダー
API を叩くときによく出てくるのが Authorization ヘッダーです。
例えば、トークンベースの認証ではこうなります。
await fetch("/api/me", {
headers: {
Authorization: "Bearer YOUR_ACCESS_TOKEN",
},
});
JavaScriptこれは、
「このリクエストは、このトークンを持っているユーザーとして送っています」
とサーバーに伝えるためのヘッダーです。
サーバー側はこのトークンを検証して、
「このユーザーは誰か」「何が許可されているか」を判断します。
セキュリティ的な注意点もセットで意識する
Authorization ヘッダーに載せるトークンは、
盗まれたらそのままなりすましに使われる可能性がある ものです。
なので、
どこに保存するか(localStorage に長期保存しない、など)
どのタイミングで付けるか
HTTPS で送っているか
といったセキュリティの観点も非常に重要になります。
ここは「Headers の書き方」だけでなく、
アプリ全体の設計の話になってきます。
Headers オブジェクトをコードで触ってみる
リクエストにヘッダーを付ける基本パターン
一番よく使うのは、fetch のオプションでオブジェクトとして指定する形です。
await fetch("/api/data", {
method: "GET",
headers: {
"X-Requested-With": "fetch-demo",
},
});
JavaScriptこのとき、内部では Headers オブジェクトに変換されています。
もう少し直接的に書くこともできます。
const headers = new Headers();
headers.set("X-Requested-With", "fetch-demo");
headers.set("Accept", "application/json");
await fetch("/api/data", { headers });
JavaScriptレスポンスのヘッダーを読む
Response 側のヘッダーも、headers プロパティから読めます。
const response = await fetch("/api/data");
console.log(response.headers.get("Content-Type"));
console.log(response.headers.get("X-RateLimit-Remaining"));
JavaScript例えば、
Content-Type で「返ってきたデータの形式」を確認するX-RateLimit-Remaining で「あと何回リクエストできるか」を知る
といった使い方ができます。
ヘッダーは「メタ情報(付帯情報)」なので、
ボディとは別に「どう扱うか」を考える必要があります。
具体例:JSON API を叩くときのヘッダー設計
よくあるパターンを一つにまとめてみる
JSON ベースの API を叩くときの、
「いい感じのテンプレート」を作ってみます。
async function fetchJson(url, options = {}) {
const defaultHeaders = {
Accept: "application/json",
"Content-Type": "application/json",
};
const mergedHeaders = {
...defaultHeaders,
...(options.headers || {}),
};
const response = await fetch(url, {
...options,
headers: mergedHeaders,
});
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
return response.json();
}
JavaScriptここでやっていることは、
JSON を送る・受け取る前提でAccept と Content-Type をデフォルトで付ける
呼び出し側が追加でヘッダーを指定できるようにマージする
という設計です。
使う側はこう書けます。
const user = await fetchJson("/api/user/1");
const created = await fetchJson("/api/users", {
method: "POST",
body: JSON.stringify({ name: "taro" }),
});
JavaScript毎回ヘッダーを手書きするのではなく、
「自分のアプリの標準ヘッダー」を一箇所にまとめておくと、
ミスも減るし、読みやすさも上がります。
初心者としてヘッダーで本当に意識してほしいこと
最後に、あなたの頭の中に残しておいてほしいポイントを整理します。
ヘッダーは「本文とは別にくっついて飛んでいくメモ書き」
Content-Type は「このボディは何形式か」を伝える(送る側の宣言)
Accept は「こういう形式で返してほしい」を伝える(受け取り側の希望)
Authorization は「誰としてアクセスしているか」を伝える(セキュリティの要)
ヘッダーは Request と Response の両方にあり、会話のルールや形式を決めている
ボディの中身と Content-Type は必ずセットで考える
おすすめの練習は、
自分が書いた fetch のコードを見直して、
このリクエストの Content-Type は何になっているべきか
Accept を付けるなら何を指定するか
レスポンスの Content-Type を見て、json() と text() をどう使い分けるか
を一つずつ言語化してみることです。
ヘッダーを「よく分からないおまじない」から、
「サーバーとの会話のルールを決める大事なメモ」 として扱えるようになったとき、
あなたのネットワーク周りのコードは一気に説得力を持ち始めます。
