今回やること
この記事では、APIエラーをHTTPの情報から切り分けます。
APIエラーでは、画面のメッセージだけでなく、実際のステータスコード、リクエスト、レスポンス本文を見ることが重要です。
JavaScriptのコードを直す前に、HTTP上で何が起きているかを確認します。
まず見る順番
APIが失敗したときは、次の順で見ます。
- Networkにリクエストが出ているか
- Request URLは正しいか
- Methodは正しいか
- Status Codeは何か
- Request HeadersとPayloadは正しいか
- Response HeadersとResponse本文に何があるか
- ブラウザだけの問題か、curlでも再現するか
この順番で見ると、フロント側、認証、URL、サーバー側のどこを見るべきかが分かれます。
ステータスコード別の入口
よく出るAPIエラーをまとめます。
| コード | まず疑うこと | 見る場所 |
|---|---|---|
400 | 送った値が不正 | Payload、Response本文 |
401 | 未ログイン、トークン期限切れ | Cookie、Authorization |
403 | 権限不足、許可設定 | ユーザー権限、CORS、IP制限 |
404 | URLやIDが違う | Request URL |
405 | メソッドが違う | Request Method |
415 | Content-Type が違う | Request Headers |
422 | バリデーションエラー | Response本文 |
429 | リクエスト過多 | RateLimit系ヘッダー |
500 | サーバー側例外 | Response本文、サーバーログ |
502 / 503 | 上流サーバーや一時停止 | インフラ、デプロイ状況 |
ステータスコードは原因そのものではなく、調査の入口です。同じ 403 でも、権限不足、CSRF、CORS、WAF、IP制限など原因は複数あります。
ケース1: 401 Unauthorized
例:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{"message":"token expired"}
401 は、認証が必要、または認証に失敗した状態です。
確認すること:
Authorizationヘッダーが付いているか- Cookieがリクエストに含まれているか
- トークンの期限が切れていないか
- ログイン後の保存処理が成功しているか
- APIの送信先ドメインがログイン時と一致しているか
DevToolsでは、対象リクエストの Request Headers を見ます。Authorization や Cookie がない場合、フロント側の認証付与処理、Cookie属性、CORSの credentials 設定を確認します。
ケース2: 403 Forbidden
例:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{"message":"permission denied"}
403 は、認証はできていても許可されていない状態で使われることが多いです。
確認すること:
- ログインユーザーにその操作権限があるか
- 管理者専用APIを一般ユーザーで呼んでいないか
- CSRF対策のトークンが欠けていないか
- IP制限やWAFで止まっていないか
- CORSエラーと混同していないか
ブラウザのConsoleにCORSエラーが出ている場合、レスポンス本文をJavaScriptから読めないことがあります。その場合はNetworkとConsoleの両方を見ます。
ケース3: 404 Not Found
例:
HTTP/1.1 404 Not Found
Content-Type: application/json
{"message":"route not found"}
404 は、対象が見つからない状態です。
確認すること:
- APIのベースURLが正しいか
- パスのスペルが正しいか
/api/users/1と/api/user/1を間違えていないか- 開発環境と本番環境でルートが違わないか
- IDの対象データが存在するか
フロント側のルーティングとAPI側のルーティングを混同すると、画面のURLは正しいのにAPIのURLが間違うことがあります。Networkの Request URL を実際に確認します。
ケース4: 405 Method Not Allowed
例:
HTTP/1.1 405 Method Not Allowed
Allow: GET, POST
405 は、パスは存在するが、そのHTTPメソッドは許可されていない状態です。
確認すること:
GETすべきAPIにPOSTしていないかPATCHのつもりがPUTになっていないか- HTMLフォームが
GETのままになっていないか - サーバー側で該当メソッドのハンドラーが実装されているか
Allowヘッダーに許可メソッドが出ているか
URLが正しくても、メソッドが違うだけで失敗します。DevToolsの Request Method を必ず見ます。
ケース5: 415 Unsupported Media Type
例:
HTTP/1.1 415 Unsupported Media Type
Content-Type: application/json
{"message":"Content-Type must be application/json"}
415 は、サーバーがその本文形式を受け付けていない状態です。
確認すること:
- JSON APIに
Content-Type: application/jsonを付けているか bodyをJSON.stringifyしているか- フォーム送信なのにJSONとして処理していないか
- ファイルアップロードで
multipart/form-dataが正しく使われているか
特にJavaScriptの fetch では、body にオブジェクトをそのまま渡してもJSONにはなりません。JSON文字列に変換し、Content-Type を合わせます。
ケース6: 429 Too Many Requests
例:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Remaining: 0
429 は、短時間にリクエストを送りすぎた状態です。
確認すること:
- 画面表示時に同じAPIを何度も呼んでいないか
- Reactなどで再レンダリングのたびにAPIを呼んでいないか
- ボタン連打対策があるか
Retry-Afterがあるか- レート制限の単位がユーザー単位かIP単位か
DevToolsのNetworkで、同じURLが大量に並んでいないかを見ます。フロント側のループや副作用の書き方が原因になることがあります。
ケース7: 500 Internal Server Error
例:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{"message":"internal server error"}
500 は、サーバー側の処理中に例外が起きた状態です。
確認すること:
- リクエスト本文に想定外の値が入っていないか
- 必須項目が欠けていないか
- サーバーログに例外が出ているか
- DB接続や外部API接続に失敗していないか
- 直前のデプロイで変更があったか
500 はサーバー側の問題であることが多いですが、フロントから不正な形の値を送った結果、サーバーが落ちている場合もあります。リクエスト内容とサーバーログをセットで見ます。
curlで再現する
ブラウザだけで失敗するのか、HTTPとして失敗するのかを分けるために、curlで同じリクエストを試します。
curl -i https://example.com/api/users/1 \
-H "Accept: application/json"
JSONをPOSTする例:
curl -i -X POST https://example.com/api/users \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
--data '{"name":"Ada"}'
ブラウザでは失敗し、curlでは成功する場合は、CORS、Cookie、ブラウザキャッシュ、拡張機能、認証情報の付け方を疑います。curlでも同じステータスになる場合は、URL、メソッド、本文、サーバー側の実装を見ます。
調査メモの書き方
人に相談するときは、次の形でまとめると原因を追いやすくなります。
【起きていること】
ユーザー作成APIが失敗する
【Request】
POST /api/users
Content-Type: application/json
body: {"name":"Ada"}
【Response】
Status: 415
body: {"message":"Content-Type must be application/json"}
【試したこと】
DevToolsでPayloadを確認した
curlでも同じステータスになった
認証トークン、Cookie、個人情報、APIキーはそのまま貼らずに伏せます。
まとめ
APIエラーは、ステータスコードだけで決めつけず、Request URL、Method、Headers、Payload、Response本文を順番に見ます。
401 は認証、403 は権限、404 はURLや対象、405 はメソッド、415 は本文形式、429 は回数制限、500 はサーバー側を入口として調査します。DevToolsとcurlの両方で確認できると、原因の切り分けがかなり楽になります。