Java | Web 基礎・HTTP・REST:HTTP 詳細 - Content-Type

Java Java
スポンサーリンク

Content-Type を一言でいうと

Content-Type は
「このボディの中身は“何の種類のデータ”かを相手に教えるためのヘッダー」
です。

中身が JSON なのか、HTML なのか、画像なのか、テキストなのか。
それをきちんと宣言することで、ブラウザやクライアント、サーバーが
「どうパースするか」「どう扱うか」を正しく判断できます。

HTTP でボディを使うなら、Content-Type を意識できるかどうかが“初級卒業ライン”だと思っていいです。


Content-Type の基本構造

形は「メディアタイプ+オプション」

Content-Type は、だいたい次のような形をしています。

Content-Type: 種類/サブタイプ; オプション...

例えば、よく見るのはこういうものです。

Content-Type: application/json
Content-Type: text/html; charset=UTF-8
Content-Type: image/png

「種類/サブタイプ」の部分を「メディアタイプ(MIME タイプ)」と呼びます。
text, image, application などが大きな分類で、その後ろに細かい種類が続くイメージです。


代表的な Content-Type とその意味

JSON を送る・返すとき

REST API で一番よく使うのがこれです。

Content-Type: application/json

意味は「ボディの中身は JSON ですよ」です。

リクエスト側で JSON を送るとき。

POST /api/users HTTP/1.1
Content-Type: application/json

{"name":"Alice","email":"alice@example.com"}
HTTP

レスポンス側で JSON を返すとき。

HTTP/1.1 200 OK
Content-Type: application/json

{"id":1,"name":"Alice","email":"alice@example.com"}
HTTP

Java(Spring)では、
リクエストを受けるときは @RequestBody と DTO、
レスポンスを返すときはオブジェクトの返り値、
と組み合わせることで、
この application/json を前提にしたやり取りが自然にできます。

HTML を返すとき

普通の Web ページを返すときは、こうなります。

Content-Type: text/html; charset=UTF-8

意味は「HTML で、文字コードは UTF-8 ですよ」です。
ブラウザはこれを見て、HTML としてレンダリングし、文字化けしないように解釈します。

プレーンテキストや画像など

プレーンなテキストなら

Content-Type: text/plain; charset=UTF-8

PNG 画像なら

Content-Type: image/png

JPEG なら

Content-Type: image/jpeg

というように、
「何の種類のデータか」を Content-Type で宣言します。


なぜ Content-Type がそんなに重要なのか

相手が「どう解釈するか」を決める材料だから

同じバイト列でも、
「JSON として読む」のか
「HTML として読む」のか
「画像として読む」のか
で意味がまったく変わります。

Content-Type が正しく付いていれば、
クライアントやサーバーは迷わず正しいパーサーを選べます。

逆に、Content-Type が間違っていたり、付いていなかったりすると、

JSON なのにテキストとして扱われてパースに失敗する
HTML なのに JSON として扱おうとしてエラーになる

といったトラブルが起きます。

セキュリティにも関わる

ブラウザは Content-Type を見て、
「これはスクリプトとして実行していいのか」
「ただのファイルとしてダウンロードすべきか」
などを判断します。

例えば、本来はただのテキストなのに
text/html として返してしまうと、
ブラウザが HTML として解釈し、
意図しないスクリプトが動く可能性があります。

だから、
「中身と Content-Type を正しく対応させる」ことは、
単なるマナーではなく、セキュリティ上も大事なポイントです。


Java(Spring)での Content-Type の扱い

リクエスト側:何を送るかを宣言する

クライアントとして API を叩くとき、
JSON を送りたいなら必ず Content-Type: application/json を付けます。

Spring の RestTemplateWebClient を使うときも、
ヘッダーに Content-Type を設定してからボディを送る、という形になります。

例えば WebClient なら、こんなイメージです。

webClient.post()
        .uri("/api/users")
        .contentType(MediaType.APPLICATION_JSON)
        .bodyValue(new UserRequest("Alice", "alice@example.com"))
        .retrieve()
        .bodyToMono(UserResponse.class);
Java

ここで contentType(MediaType.APPLICATION_JSON) が、
HTTP の Content-Type: application/json に対応します。

レスポンス側:何を返すかを宣言する

Spring MVC では、
@RestController + オブジェクト返り値
というだけで、基本的には application/json が付きます。

HTML を返したい場合は、
テンプレートエンジン(Thymeleaf など)を使ったり、
@Controller でビュー名を返したりすると、
text/html が付くように設定できます。

また、明示的に指定したいときは、

@GetMapping(value = "/text", produces = "text/plain;charset=UTF-8")
public String text() {
    return "hello";
}
Java

のように produces 属性で指定することもできます。


Content-Type と Accept の関係

「送るときの宣言」と「欲しいときの希望」

Content-Type:
「今送っているボディは、こういう種類のデータですよ」

Accept:
「レスポンスは、この種類のデータで返してほしいです」

という関係です。

例えば、クライアントが

GET /api/users/1 HTTP/1.1
Accept: application/json
HTTP

と送ると、
「JSON で返してほしい」という希望になります。

サーバーはそれに応じて

HTTP/1.1 200 OK
Content-Type: application/json

{"id":1,"name":"Alice"}
HTTP

のように返します。

この「Accept と Content-Type の組み合わせ」で、
クライアントとサーバーが「どの形式で話すか」をすり合わせているイメージです。


初心者向けまとめ:Content-Type を自分の言葉で説明するなら

あなたの言葉で整理すると、こうなります。

Content-Type は、
「HTTP のボディに入っている中身が、どんな種類のデータかを示すヘッダー」で、
application/jsontext/html などのメディアタイプで表現する。

クライアントが JSON を送るときは Content-Type: application/json を付け、
サーバーが JSON を返すときも同じく application/json を付ける。
中身と Content-Type がズレると、パースエラーや表示崩れ、セキュリティ問題の原因になる。

Java(Spring)では、
@RequestBody@RestController を使うことで、
JSON 前提の Content-Type のやり取りが自然にできるようになっているが、
「何を送っていて、何を返しているのか」を意識して設計できるようになると、一気に一人前に近づく。

もしよければ、
「自分が作りたい API のリクエストとレスポンスの Content-Type は何か?」
を一つずつ言語化してみて。
それを説明できるようになったとき、Content-Type はもう“おまけの文字列”ではなく、“あなたがコントロールするプロトコルの一部”になっているはず。

タイトルとURLをコピーしました