1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

1. 「API エラー」の正体は502と400で全然違った ― React×Django環境で踏んだ2つのエラー

1
Posted at

はじめに

個人で技術検証をしていて、React から Django の API を呼ぶところで、2回エラーにぶつかりました。どちらも画面上は「API エラー」でしたが、1回目は 502、2回目は 400 で、原因はまったく別のところにありました。

この記事では、2つのエラーで何が起きていたのかと、エラーの数字から探す場所をどう絞ったかを書きます。React や Django を触り始めた人、Docker で開発環境を作り始めた人の参考になればうれしいです。

この記事のまとめ

  • 502 は「たどり着けない」:リクエストが Django まで届いていない
  • 400 は「届いたけど断られた」:Django には届いていて、そのうえで断られている

環境

  • フロントエンド:Vite + React 19 + TypeScript(Node.js 22)
  • バックエンド:Django 6.1
  • 構成:React の画面から /api/... を呼び、Vite のプロキシで Django に転送する
  • 2回目の時点では、Docker Compose で Django と Vite を起動
  • 開発は Claude Code と一緒に進めています

1つ目:502 エラー(たどり着けない)

何が起きたか

React の画面から Django の API を呼んだら、502 エラーになりました。Django を直接呼ぶと成功するのに、React の画面から Vite を経由すると失敗する、という状態です。

どう絞り込んだか

「直接なら成功、経由だと失敗」なので、Django そのものではなく、Vite から Django へ転送する区間に問題があると分かります。区間を分けて確かめるだけで、探す場所がぐっと絞れました。

原因

Node.js では localhost が IPv6 の ::1 として解決されるのに、Django は IPv4 の 127.0.0.1 で待ち受けていました。Vite の転送先に localhost と書いていたため、Django がいない場所にリクエストを送っていたことになります。

対処

Vite のプロキシの転送先を、localhost ではなく http://127.0.0.1:8000 に変えて解決しました。

vite.config.ts(変更のイメージ)
export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://127.0.0.1:8000', // localhost から変更
      },
    },
  },
})

この原因は、Claude Code がエラーログから見つけて、修正と再確認までしてくれました。

「localhost と書いておけば大丈夫」という思い込みは危ない、というのが一番の学びでした。

2つ目:400 エラー(届いたけど断られた)

何が起きたか

検証環境を Docker で動くようにしたあと、画面に「API エラー: 400」と表示されました。

最初は、1つ目と同じように「つながっていないのかな」と思いました。でも実際は、リクエストは Django まで届いていて、そのうえで Django に断られていました。

原因

Django には、受け付けるリクエストの宛先を決めておく ALLOWED_HOSTS という設定があります。一覧にない宛先からのリクエストは、400 で断られます。

この一覧に、Docker でのサービス名である backend が入っていませんでした。Docker にしたことで、Django から見たリクエストの宛先が変わっていたわけです。

対処

ALLOWED_HOSTS に backend を追加して解決しました。

settings.py(変更のイメージ)
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "backend"]

502 と 400 の違い

どちらも画面上は同じ「API エラー」でしたが、意味はまったく違いました。

502 400
ひとことで たどり着けない 届いたけど断られた
リクエストは Django に届いたか 届いていない 届いている
探す場所 Django までの経路(プロキシの転送先など) Django 側の設定や、送った内容
今回の原因 localhost が IPv6 で解決され、IPv4 で待つ Django に届かなかった ALLOWED_HOSTS に Docker のサービス名がなかった

学んだこと

エラーの数字をちゃんと読む。 502 なら「途中で止まっている」、400 なら「相手には届いている」。数字の意味を知っているだけで、探す場所が半分くらいに絞れます。今回の 400 も、数字の意味を知っていれば「つながっていない」と勘違いせずに済みました。

区間を分けて確かめる。 「直接なら成功、経由だと失敗」のように、どこまでは動いているかを確かめると、原因のある区間が見えてきます。

AI に直してもらっても、理由は自分で理解する。 502 の原因は Claude

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?