415 Unsupported Media Type:サーバーとクライアントの「言葉のすれ違い」を解き明かす
ネットワークエンジニアとして現場を歩いていると、HTTPステータスコードの中でも、ある種「もどかしい」エラーに遭遇することがあります。それが 415 Unsupported Media Type です。
「データは送った、サーバーも応答している。なのにエラーになる」。
このエラーは、単なる設定ミスではなく、サーバーとクライアントの間の「握手」が成立していないことを指します。今回は、この415エラーの正体と、現場で遭遇した時に最短で切り分けるための知見を共有しましょう。
—
1. 415エラーの正体:何が「サポートされていない」のか
RFC 7231 (HTTP/1.1 Semantics) によれば、415エラーは「サーバーがリクエストを処理しようとしたが、リクエストボディのメディアタイプ(`Content-Type`)が、リソースのメソッドでサポートされていない」場合に返されます。
ここで重要なのは、サーバーはリクエストを受け取っているが、その中身をどう解釈していいか分からないという点です。
現場でよくある発生パターン
1. APIの不整合: クライアントが `application/xml` で送ったのに、サーバーは `application/json` しか受け付けない設計だった。
2. デフォルト値の罠: フレームワーク(SpringやDjango等)が自動的に `application/x-www-form-urlencoded` を期待しているのに、クライアントが JSON を投げ込んだ。
3. 誤ったヘッダー指定: ファイルアップロード時に、本来必要な `multipart/form-data` ではなく、別の型を指定してしまった。
—
2. 通信フロー:握手が成立しない瞬間
パケットレベルで何が起きているのか、シーケンスを追ってみましょう。
[Client] [Server]
| |
|– POST /api/data HTTP/1.1 ——————–>|
| Content-Type: text/plain |
| [リクエストボディ: {“id”: 1}] |
| |
| (サーバー側: 「text/plainは扱えない!」) |
|<-- HTTP/1.1 415 Unsupported Media Type --------|
| (レスポンスボディ: エラー詳細など) |
クライアントは「プレーンテキストとしてデータを送った」つもりですが、サーバーのコントローラー側は「JSONとしてパースしなければならない」と待ち構えています。この認識のズレが415を引き起こします。
---
3. 実践:デバッグと検証のためのコード
現場で「なぜ415が出るのか?」を切り分ける際、私はまず `curl` で最小構成のリクエストを投げます。
curl での再現と確認
明示的に Content-Type を指定して疎通確認
curl -v -X POST http://api.example.com/data \
-H “Content-Type: application/json” \
-d ‘{“id”: 1}’
-v オプションでリクエストヘッダーとレスポンスヘッダーを詳細に確認するのがコツです
Python (requests) での送信例
import requests
url = “http://api.example.com/data”
headers = {
# ここが間違っていると415が出る
“Content-Type”: “application/json”
}
data = {“id”: 1}
response = requests.post(url, json=data, headers=headers)
if response.status_code == 415:
print(“エラー: サーバーが期待するメディアタイプと一致していません。”)
フロントエンド (Fetch API) での注意点
Fetch APIで `body: JSON.stringify(data)` を使う場合、明示的に `Content-Type` を設定しないと、サーバーが期待する型と合致せず415になるケースが多々あります。
fetch(‘http://api.example.com/data’, {
method: ‘POST’,
headers: {
// これを忘れると、デフォルトのテキスト形式で送られ、サーバーがJSONと認識できず415になることがある
‘Content-Type’: ‘application/json’
},
body: JSON.stringify({ id: 1 })
});
—
4. 解決のためのインフラ・設計Tips
415エラーを未然に防ぐ、あるいは適切に扱うための「エンジニアの作法」を3つ伝授します。
1. AcceptヘッダーとContent-Typeを混同しない:
- `Content-Type` は「送るデータの型」です。
- `Accept` は「受け取りたいデータの型」です。
- 415が出たら、必ず `Content-Type` を疑ってください。
2. サーバー側で詳細なログを出す:
- Webサーバー(NginxやApache)のログだけでなく、アプリケーションフレームワークが「なぜ拒否したか」の理由をログに出すように設計してください。「415が返った」という事実はログに出ていても、肝心の「どのメディアタイプが期待されていたか」までログにないと、調査は難航します。
3. API仕様書の整備:
- Swagger(OpenAPI)などで、各エンドポイントがどの `Content-Type` を受け入れるかを明記しましょう。結局のところ、多くの415エラーは「仕様の伝達ミス」から生まれます。
—
最後に:ネットワークは「対話」である
HTTPステータスコードは、サーバーからの「声」です。415 Unsupported Media Typeは、決して「お前はダメだ」と突き放しているわけではありません。「あなたが使っている言語(メディアタイプ)は理解できないから、別の言葉で話してくれないか?」という、対話のプロトコルエラーなのです。
現場で415に遭遇したら、まずは焦らず、送ったデータの形式とサーバーが要求する形式を並べて比較してみてください。パケットを眺めれば、必ずどこかで「言葉の食い違い」が見つかるはずです。
皆さんのネットワークが、今日も滞りなく繋がっていることを願っています。
コメント