HTTP ステータス コード 404 か 410 か 301 をいつ返すべきか(推測をやめましょう)
バックエンド開発者は常にHTTPステータスコードを間違えます。REST APIで実際に重要なコードについての実用ガイドです——404と410、301と302、429のレート制限、および200ステータスコードにエラーボディを含める誤用パターン。
200を返しました {"error": "user not found"} ボディに含まれています。あなたの301は実際には302です。削除されたリソースは永遠に404を返します。開発者が頻繁に間違えるステータスコードについて、そして代わりに返すべきものについて詳しく説明します。
4xx と 5xx:同じバケットではない
HTTPステータスコードにおける最も基本的な分類: 4xxはクライアントの問題であり、5xxはあなたの問題です理論的にはシンプルですが、実際には常に違反されています。
最も一般的な間違い:バリデーションエラーに対して500を返す 500を返すユーザーが不正なJSONをAPIに送信しました。これは 400 Bad Request — パイロットが間違っています。500はクライアントに「システムがクラッシュした」と伝えるため、アラートが発生し、サーバーのエラーとしてログが記録され、自動システムがリトライを繰り返す(悪い日をさらに悪化させる)ことになります。クライアントが不正なデータを送信した場合、4xxを返すべきです。
404 と 410:削除されたリソースの問題
404 Not Found は「今はないが、あとで試してみてください」と意味します。スクリーニング(Googlebotを含む)は404を一時的なものと見なし、無限に再チェックを続けます。
410 Gone は「そのリソースは永久に削除されました。もう尋ねないでください」と意味します。Googlebotは410のURLをインデックスから早く削除し、それらをスキャン停止します。これはSEOや大規模サイトのクロール予算に影響します。
実用的なルール:APIがリソースを硬削除し、戻ってこない場合、その後のリクエストに対して410を返します。削除されたリソースに対して404を優先する理由は、復元可能性がある場合(ソフト削除、回復期間、再発行可能な投稿など)です。それ以外では、410がより誠実であり、検索エンジンが感謝します。
301 と 302(そしてなぜ307/308が存在するか)
301 Moved Permanently:このURLは永遠に消えました。新しいURLを使用してください。ブラウザは301を積極的にキャッシュします。検索エンジンは目的地にリンクエクイティを移動します。ドメインを統合したり、サイトを永久に移動させたい場合、301が望ましいです。
302 Found:一時的に別のURLに移動し、後に元のURLに戻ってください。キャッシュされません。リンクエクイティの移動もありません。ログインリダイレクト、一時的なメンテナンスページ、A/Bテストに使用します。
失敗モード:302を永久的な移動に使用する。あなたは「同じこと、ただ違うだけ」と考えていますが、検索エンジンは302を通じてリンクエクイティを伝搬しません。年間のSEO作業は古いURLに残り、新しいURLは何もランキングできません。何かを永久に移動した場合、301を使用してください。
それから 307 Temporary Redirect と 308 Permanent Redirect。これらはメソッドセーフなバリエーションです:ブラウザが301/302を追跡する際にPOSTをGETに下げる可能性がありますが、307/308は元のHTTPメソッドを維持します。APIエンドポイントがPOSTボディを受け入れる場合、307(一時)または308(永久)はメソッドを維持します。
| コード | タイプ | キャッシュ? | メソッドを維持? | 使用する場合 |
|---|---|---|---|---|
| 301 | 永久的 | はい | いいえ(GETに下げる可能性あり) | 永久的なサイト移動、URL統合 |
| 302 | 一時的 | いいえ | いいえ(GETに下げる可能性あり) | ログインリダイレクト、一時的な不可用性 |
| 307 | 一時的 | いいえ | はい | API POSTエンドポイントのための一時リダイレクト |
| 308 | 永久的 | はい | はい | API POSTエンドポイントのための永久リダイレクト |
401 と 403:認証と認可
名前は混乱しています。 401 Unauthorized 実際に意味するのは 未認証 — ログインされていない、または認証情報が欠落または無効です。 403 Forbidden は、あなたが認証されていますが、このリソースにアクセスする権限がないことを意味します。
実用的な違い:401はログイン画面またはトークンの再取得を促すべきです。403はアクセス拒否メッセージを表示すべきです。間違ったものを返すと、クライアントが認証情報を要求するか、諦めるかを判断できません。
セキュリティの側面もあります。一部のAPIは、呼び出し者がアクセスできないリソースに対して404を返すことで、そのリソースが存在することを漏らすのを防ぎます。別のテナントのリソースに対して403を返すと、そのリソースが存在することを確認します。404を返す方が情報セキュリティが高く、正当なユーザーのデバッグが難しくなるものの、脅威モデルに合った選択をし、一貫性を保ちましょう。
429:レート制限、実際に役立つヘッダー付き
単に 429 Too Many Requests は不満です。429に Retry-After ヘッダーを含むのは実際に役立ちます。
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1746374400
Retry-After 秒数またはHTTP日付を含むことができます。よく振る舞うクライアントは自動的にリトライを実行します。ヘッダーがない場合、エラーコードを返し、クライアントが再試行のタイミングを判断するという方法を採用しているため、多くのクライアントはすぐにエンドポイントを繰り返し送信し、レート制限の目的を達成できません。
レート制限のために503を返すべきではありません。503は「サービスが利用できません」という意味であり、インフラがダウン、デプロイ中、回路ブレーカーが開いている場合に使われます。レート制限はポリシーの決定であり、サービスの障害ではありません。429がまさにこのために存在しています。
「200 とエラーボディ」の反パターン
これは生産環境のAPIで頻繁に現れ、やめなければなりません:
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "error", "message": "user not found"}
これはHTTPの意味論をすべて破壊します。モニタリングツールはリクエストを成功として報告します。ロードバランサはそれを通過させます。クライアントライブラリは例外を投げません。ログはきれいに見えますが、ユーザーはエラーを確認します。解決策は1行のコードです:正しいステータスコードを返すだけです。 200は成功を意味します。 成功しなかった場合、200を返さないでください。
これは201と200のリソース作成に関する同じ論理を適用します。POSTを /users 新しいユーザーを作成した場合、 201 Created で包まれており、 Location ヘッダーを含め、新しいリソースへのリンクを示します。200を返すと、クライアントが追加のリクエストを実行する情報が失われます。
APIシナリオ → 正しいステータスコード
REST API開発で最も頻繁に発生するシナリオに対する参照表です:
| シナリオ | ステータスコード | 注記 |
|---|---|---|
| リクエストボディが不正なJSON | 400 Bad Request | パースエラーを示すメッセージを含める |
| リクエストに欠落または無効なフィールド | 422 Unprocessable Entity | 422は400よりも、セマンティックバリデーション失敗に対して正確です |
| 認証トークンが欠落または期限切れ | 401 Unauthorized | 含める WWW-Authenticate ヘッダー |
| 認証済みだが権限なし | 403 Forbidden | または、リソースの存在を隠す必要がある場合に404 |
| リソースが見つからない、一時的な欠如または不明なリソースの場合に | 404 Not Found | 返す |
| リソースが永久に削除された | 410 Gone | スクリーニングは再チェックを早く終了します |
| 新しいリソースを作成 | 201 Created | 追加する Location: /resources/new-id ヘッダー |
| DELETEが成功し、ボディなし | 204 No Content | 200で空のJSONオブジェクトを返さないでください |
| 永久的なURL変更 | 301 Moved Permanently | 検索エンジンがリンクエクイティを移動します |
| 一時リダイレクト | 302 Found | キャッシュされず、エクイティの移動もありません |
| レート制限を超えました | 429 Too Many Requests | 常に含める Retry-After |
| 予期しないサーバー例外 | 500 Internal Server Error | スタックトレースをボディに漏らさないでください |
| 上流の依存関係がダウン | 503 Service Unavailable | 追加する Retry-After ダウンタイムが限定されている場合 |
| POSTリダイレクト、メソッドを維持 | 307または308 | 307は一時的、308は永久的 |
PR中でステータスコードの意味を確認する必要がある場合、 HTTPステータスコードリファレンスツール は、スペック定義、典型的な使用例、およびどのRFCが定義しているかを提供します。
リダイレクトチェーンの確認
サイト移行やURL構造の変更後、完全なリダイレクトチェーンを確認することが価値があります—特に301が後に別の場所に変更された場合、複数のホップチェーンがリンクエクイティを損失させます。この場合、 リダイレクトチェッカー チェーンをトレースし、各ステータスコードを順に表示することで、すべてが1ホップで解決されていることを確認できます。
