Accept を一言でいうと
Accept ヘッダーは
「サーバーさん、レスポンスは“この種類のデータ”で返してくれると嬉しいです、という希望を伝えるヘッダー」
です。
クライアント(ブラウザやアプリ)が
「JSON が欲しいのか」「HTML が欲しいのか」「画像が欲しいのか」
をサーバーに伝えるための“希望表明”だと思ってください。
Content-Type との違いからイメージする
Content-Type は「今送っている中身はこれです」
まず、よくセットで出てくる Content-Type を思い出しましょう。
Content-Type は、
「このリクエスト(またはレスポンス)のボディは、こういう種類のデータです」
という“事実の宣言”でした。
例:JSON を送るとき
POST /api/users HTTP/1.1
Content-Type: application/json
{"name":"Alice"}
HTTPこれは
「今送っているボディは JSON ですよ」
という意味です。
Accept は「こういう形式で返してほしいです」
一方 Accept は、
「レスポンスは、この種類のデータで返してほしいです」
という“希望”を伝えます。
例:JSON で返してほしいとき
GET /api/users/1 HTTP/1.1
Accept: application/json
HTTPこれは
「ユーザー 1 の情報をください。できれば JSON で欲しいです」
という意味になります。
サーバーはこれを見て、
「じゃあ JSON で返そう」と判断し、
HTTP/1.1 200 OK
Content-Type: application/json
{"id":1,"name":"Alice"}
HTTPのように返します。
まとめると:
Content-Type → “今送っている中身はこれ”
Accept → “返してほしい中身はこれ”
Accept の基本的な書き方
メディアタイプを列挙する
Accept には、欲しいメディアタイプ(MIME タイプ)を書きます。
一番シンプルな例はこれです。
Accept: application/json
HTTP「JSON で返してほしい」です。
HTML が欲しいなら
Accept: text/html
HTTP画像なら
Accept: image/png
HTTPのように書きます。
複数候補を並べることもできる
「これが第一希望だけど、ダメならこれでもいいよ」と
複数書くこともできます。
Accept: application/json, text/plain
HTTPこの場合、
「JSON がいいけど、無理ならプレーンテキストでもいいよ」
という意味になります。
さらに細かく「優先度(重み)」も付けられますが、
初心者のうちは「とりあえず application/json を指定する」くらいで十分です。
サーバー側は Accept をどう使うか
コンテンツネゴシエーションという考え方
サーバーは、
「自分が返せる形式」と
「クライアントの Accept」
を見比べて、
どの形式で返すかを決めます。
これを「コンテンツネゴシエーション」と呼びます。
例えば、サーバーが
JSON と HTML の両方で返せるエンドポイント
を持っているとします。
クライアント A:
Accept: application/json
HTTPクライアント B:
Accept: text/html
HTTPこのときサーバーは、
A には JSON を
B には HTML を
返す、ということができます。
同じ URL でも、Accept によって“見え方”を変えられるわけです。
Java(Spring)でのイメージ
Spring MVC では、produces 属性やメッセージコンバータの設定によって、
「どの Content-Type で返すか」を制御できます。
例えば、JSON 専用の API なら、
@GetMapping(value = "/api/users/{id}", produces = "application/json")
public UserResponse get(@PathVariable Long id) { ... }
Javaのようにしておけば、
基本的に application/json で返す前提になります。
実務では、
「API は JSON 固定」
「画面は HTML 固定」
ということが多いので、
Accept をガチガチに使い分ける場面はそこまで多くありません。
それでも、
「クライアントが Accept で希望を出し、サーバーが Content-Type で応える」
という構図を理解しておくと、プロトコルの見え方が一段クリアになります。
Java 開発者視点での Accept の使いどころ
自分がクライアントになるときに意識する
Java で外部の REST API を叩くとき、
「JSON で返してほしい」のに Accept を付け忘れると、
相手が HTML や XML を返してくることがあります。
WebClient や RestTemplate を使うとき、
webClient.get()
.uri("/api/users/1")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(UserResponse.class);
Javaのように accept(MediaType.APPLICATION_JSON) を付けると、
HTTP の Accept: application/json に対応します。
これで、
「このクライアントは JSON を期待しているんだな」
と相手に伝えられます。
ブラウザは自動で Accept を付けてくれる
ブラウザからのアクセスでは、
ブラウザが自動で Accept を付けてくれます。
例えば、普通に URL を開くときは、text/html を含む Accept が送られます。
逆に、JavaScript の fetch で JSON API を叩くときは、
フロント側で Accept: application/json を付けることが多いです。
バックエンドを書くときに
「ブラウザはこういう Accept を送ってくるんだな」
とログを眺めてみると、理解が一気に深まります。
初心者向けまとめ:Accept を自分の言葉で説明するなら
あなたの言葉で整理すると、こうなります。
Accept は、
「クライアントがサーバーに対して、レスポンスはこの形式で返してほしいと希望を伝えるヘッダー」で、Accept: application/json なら「JSON で返してほしい」、Accept: text/html なら「HTML で返してほしい」という意味になる。
Content-Type が「今送っている中身の種類」を表すのに対して、
Accept は「これから受け取りたい中身の種類」を表す。
Java で外部 API を叩くときに Accept: application/json を付けることで、
「JSON を期待している」という意図を相手に伝えられるようになる。
もしよければ、
「同じ /users/1 に対して、HTML で返すパターンと JSON で返すパターン」を
Accept と Content-Type の組み合わせでどう表現するか、
自分の言葉で書き分けてみて。
そこを説明できるようになったとき、Accept はもう“謎のヘッダー”ではなく、“会話の希望を伝える道具”になっているはず。
