HTTPステータスコードとは ― 404・502・503の意味
HTTP
HTTPステータスコードとは、リクエストの結果を表す3桁の数字
画面に 502 Bad Gateway と出たら、原因はたいていサイトの側にあり、自分のPCの設定を変えても直りません。リクエストを中継するサーバが、奥のサーバから正しい応答をもらえなかったことを表す番号だからです。このようにサーバがリクエストの結果を3桁の数字で返すものが、HTTPステータスコードです。
番号を読めれば、調べる先を絞れます。APIの401でURLを疑ったり、504でアプリのエラーログだけを探したりする遠回りが減ります。
この先を読むと、1桁目の分類と、401と403、502と504のように似た番号の違いが分かります。どの機器が返した番号かを確かめる手順も説明します。
1桁目で分かる5つの分類:1xx〜5xx
ステータスコードは、HTTPのレスポンスの1行目に入る100から599までの数字です。RFC 9110は1桁目で5つに分類していて、下2桁に分類の意味はありません。1桁目が4か5かを見れば、問題のある側の見当がつきます。
| 分類 | 意味 | 代表的な | 読み方 |
|---|---|---|---|
| 1xx | 途中経過 | 100、101 | 処理の途中のお知らせで、ふだんは目にしません |
| 2xx | 成功 | 200、201、204 | リクエストを受け付けて処理できました |
| 3xx | リダイレクト | 301、302、304 | 完了するには、別のURLへ行くなどの追加の動作が要ります |
| 4xx | クライアントエラー | 400、401、403、404、429 | リクエストの側に問題があるとサーバが判断しました |
| 5xx | サーバエラー | 500、502、503、504 | サーバの側でリクエストを処理できませんでした |
知らない番号も1桁目で読めます。たとえば471は登録のない番号ですが、4で始まるので、RFC 9110の決まりでは400と同じに扱います。
番号の後ろの Not Found のような語は理由句と呼び、人が読むための説明です。理由句は置き換えも省略もできるので、プログラムは数字で判断します。
200・301・302・304の意味:成功とリダイレクト
200はリクエストが成功したことを表す、いちばんよく見る番号です。APIでは、データを新しく作れたときに201、成功して返す本文がないときに204を使います。どれも1桁目が2なので、成功を表します。
301と302の違い:移転が恒久か一時か
301と302は、どちらも Location ヘッダで移動先のURLを知らせる番号です。ブラウザは自動で移動先を開くので、利用者の画面はどちらも同じです。違いは、301は恒久の移転で、302は一時的な移動という点にあります。
httpからhttpsへの切り替えやドメインの変更のように、元に戻さないなら301を使います。期間限定のキャンペーンで別のページへ案内するときのように、あとで元のURLへ戻すなら302を使います。Googleの説明では、恒久なら転送先を、一時なら元のページを検索結果に出します。
301はブラウザに覚えられることがあるので、設定を戻しても転送が続く場合があります。動作を試している間は302にしておくと、やり直しが楽です。
フォームの送信でPOSTを使っているときは、もう1つ気をつけることがあります。301と302では、ブラウザが移動先へのリクエストをGETに変えることがあります。メソッドを保ちたいときは、307か308を使います。
| 移動の | POSTが | メソッドを |
|---|---|---|
| 恒久 | 301 | 308 |
| 一時 | 302 | 307 |
304:変更がないのでキャッシュを使う
304は、エラーではありません。ブラウザは前に受け取ったファイルをキャッシュとして保存していて、変更があるかどうかをサーバに尋ねることがあります。変更がなければ、サーバは本文のない304を返します。ブラウザは保存してあるファイルを使うので、通信量が減ります。同じようにファイルのコピーを持って配信する仕組みには、CDNがあります。
400・401・403・404・429の意味:リクエスト側の問題
4xxは、サーバがリクエストの側に問題があると判断したときの番号です。自分のPCの故障を指すわけではありません。リンク切れや権限の設定ミスのように、サイトの側を直す場合もあります。
| 番号 | 意味 | よく | 最初に |
|---|---|---|---|
| 400 Bad Request | リクエストの形が正しくない | 壊れたJSON、ヘッダの書き間違い | 送った本文とヘッダ |
| 401 Unauthorized | 有効な認証情報がない | ログイン切れ、APIキーの付け忘れ | トークンやAPIキーの有効期限 |
| 403 Forbidden | 理解したうえで実行を断る | 権限の不足、接続元の制限 | ユーザーの権限とアクセス制限の設定 |
| 404 Not Found | 対象が見つからない | URLの誤り、削除されたページ | URLのつづりとリンク元 |
| 429 Too Many Requests | 送りすぎ | 回数制限の超過 | Retry-After ヘッダと呼び出しの回数 |
401と403の違い:相手が分からないか、分かったうえで断るか
401は、有効な認証情報が無いことを表します。ログインしていない、APIキーの期限が切れた、といった場面です。認証情報を直して送り直せば、通る見込みがあります。
403は、サーバがリクエストを理解したうえで実行を断る番号です。相手が誰か分かっていても、権限がなければ403になります。同じ認証情報で送り直しても、ふつうは結果が変わりません。理由が認証情報と関係ないこともあります。たとえば、接続元のアドレスで制限しているサイトでも403を返せます。
401の名前は Unauthorized ですが、実際の意味は未認証です。名前につられて、権限の設定から調べ始めないようにします。
404:ページがないか、あることを教えたくないか
404は、対象が見つからないことを表します。RFC 9110では、対象の存在を教えたくないときにも使えます。そのため、権限のない人に403の代わりに404を返すサービスもあります。ログイン中の人だけに見えるURLが404になったら、権限も疑います。
404は、ないのが一時的か恒久かを示しません。恒久になくなったと分かっているときの番号には、410があります。
429:回数の上限を超えた
429は、決まった時間内に送りすぎたことを表します。RFC 6585で定められた番号で、待つべき時間を Retry-After ヘッダで示せます。プログラムから呼ぶときは、すぐ再送を繰り返さず、示された時間を待ちます。AWSでは、API Gatewayのスロットリングがこの回数の制限にあたります。
500・502・503・504の違い:どこで止まったか
5xxは、サーバの側がリクエストを処理できなかったときの番号です。違いを読むには、番号を作った機器に注目します。多くのサイトでは、ブラウザと奥のサーバの間にロードバランサやリバースプロキシが入っています。500はふつう奥のサーバのアプリが作る番号で、502と504は間で中継するサーバが作る番号です。
| 番号 | 何が | 最初に |
|---|---|---|
| 500 Internal Server Error | サーバが処理の途中で想定外の状態になった | アプリのエラーログ |
| 502 Bad Gateway | 中継するサーバが、奥のサーバから不正な応答を受け取った | 奥のサーバが動いているか、接続先の設定 |
| 503 Service Unavailable | 過負荷やメンテナンスで、今は処理できない | サーバの負荷と台数、メンテナンスの予定 |
| 504 Gateway Timeout | 中継するサーバが待っても、奥のサーバの応答が来なかった | 奥のサーバの処理時間、経路、待ち時間の設定 |
500:アプリが処理を続けられなかった
500は、サーバが想定外の状態になったときの番号です。プログラムの不具合や、データベースにつながらないときの例外処理の漏れなどで起きます。手前の機器は番号を中継しているだけなので、手がかりはアプリのログにあります。
502と504の違い:返事がおかしいか、返事が来ないか
502は、中継するサーバが奥のサーバから不正な応答を受け取ったときの番号です。504は、奥のサーバの応答を時間内に受け取れなかったときの番号です。502は返事がおかしく、504は返事が来ません。
AWSのALBの資料を見ると、原因の違いが具体的に分かります。502の例は、接続を拒否された場合や、処理の途中で接続を切られた場合、応答のヘッダが壊れている場合です。504の例は、10秒以内に接続できない場合や、接続後に待ち時間の上限まで応答がない場合です。
ただし、どこまでを502と呼ぶかは製品で少しずつ違います。CloudFrontは、オリジンのサーバに接続できないと502を返し、ファイアウォールに遮られたときは504を返します。番号で調べる方向を決めたら、その機器の資料で原因の一覧を確かめます。
503:今は受けられないが、時間をおけば直る見込み
503は、過負荷やメンテナンスで一時的に処理できないことを表します。Retry-After ヘッダで、待つ時間の目安を示せます。奥のサーバが自分で返すこともあれば、中継する機器が返すこともあります。ALBは、振り分け先のサーバが1台も登録されていないときなどに503を返します。
サイトをメンテナンスで止めるときは、案内のページを503で返します。Googleは5xxの応答の中身を無視するので、案内の文が検索結果に載るのを防げます。逆に、過負荷のサーバが必ず503を返すとは限りません。接続そのものを受け付けなくなることもあります。
押してみる:起きたことと返る番号
起きたことを選ぶと、返る番号と番号を作った機器が切り替わります。構成はAWSのALBをサーバの前に置いた例で、ほかの機器では番号が変わることもあります。
- ブラウザ番号を
受け取る - ロードバランサ中継する
- サーバ404を
返す
- ブラウザ番号を
受け取る - ロードバランサ中継する
- サーバ401を
返す
- ブラウザ番号を
受け取る - ロードバランサ中継する
- サーバ403を
返す
- ブラウザ番号を
受け取る - ロードバランサ中継する
- サーバ429を
返す
- ブラウザ番号を
受け取る - ロードバランサ中継する
- サーバ500を
返す
- ブラウザ番号を
受け取る - ロードバランサ502を
返す - サーバ接続を
拒否する
- ブラウザ番号を
受け取る - ロードバランサ503を
返す - サーバ届かない
- ブラウザ番号を
受け取る - ロードバランサ504を
返す - サーバ処理が
終わらない
ステータスコードの確かめ方:開発者ツールとcurl
ブラウザの開発者ツールで見る
画面に番号が出ないときも、ブラウザの開発者ツールで確かめられます。1つのページは多くのファイルでできているので、画像だけが404という場合も見つかります。手順はChromeの例です。
- Control+Shift+J を押します。Macでは Command+Option+J です。
- Network タブを開きます。
- ページを読み込み直します。
- Status 列で、ファイルごとの番号を読みます。
- 行を押すと、レスポンスのヘッダを読めます。
リダイレクトの前後を比べたいときは、Preserve log にチェックを入れます。ページを移動しても、それまでのリクエストが一覧に残ります。
curlコマンドで見る
curlは、コマンドからHTTPのリクエストを送るツールです。-I を付けると、本文を除いたヘッダだけが表示されます。次の出力は、このサイトのhttpのURLを開いたときのものです。
$ curl -I http://nwtextbook.jp/ HTTP/1.1 301 Moved Permanently Server: CloudFront Location: https://nwtextbook.jp/ # 301が番号、Locationが移動先
-I はHEADメソッドで送るので、ブラウザのGETとは結果が違うサーバもあります。番号が食い違うと感じたら、-i でGETを送り、本文も含めて確かめます。リダイレクトを最後まで追うときは -L を足します。番号だけを取り出す書き方もあり、監視の簡単な確認に使えます。
$ curl -s -o /dev/null \
-w '%{response_code}\n' \
https://example.com/
200番号が出ないときは、HTTPの手前で止まっている
ステータスコードはHTTPのレスポンスに入っているので、サーバと接続できなければ番号は出ません。Chromeに次のような表示が出たら、HTTPのやり取りが始まる前に止まっています。Webページが表示されるまでの流れの、どこで止まったかを考えます。
| Chromeの | 止まった | 調べる |
|---|---|---|
| ERR_NAME_NOT_RESOLVED | 名前からIPアドレスを引けなかった | DNSの設定とドメイン名 |
| ERR_CONNECTION_REFUSED | サーバに接続を拒否された | ポート番号とサーバの待ち受け |
| ERR_CONNECTION_TIMED_OUT | 接続の返事が来なかった | pingとtracerouteで確かめる経路、ファイアウォール |
| ERR_CERT_DATE_INVALID | 証明書の確認で止まった | 証明書の有効期限と、PCの時計 |
ロードバランサ・CDN・プロキシが返す5xxの読み方
5xxを見たら、番号の意味の次に、どの機器が返したかを確かめます。同じ502でも、CDNが返したのか、ロードバランサが返したのかで、調べる相手が変わります。
レスポンスヘッダで手がかりを探す
最初の手がかりはヘッダです。Server はレスポンスを返したサーバのソフトの名前を、Via は途中で通ったプロキシを示します。次の出力は、このサイトの存在しないURLを開いたときのものです。
$ curl -I \
https://nwtextbook.jp/no-page/
HTTP/2 404
server: AmazonS3
x-cache: Error from cloudfront
via: 1.1 ...cloudfront.net
# 番号はCloudFront、本文はS3server だけを見るとS3が404を返したように読めますが、実際は違います。このサイトはS3にファイルを置き、CloudFrontで配信しています。S3がエラーを返すと、CloudFrontは設定に従って番号を404にして、S3に置いた案内のページを本文に使います。server はこの本文の出どころを示しているだけです。
こうした設定がなければ、CloudFrontは奥のサーバが返した番号をそのまま中継します。ヘッダは番号を作った機器を示すとは限らず、サイトの設定で消すこともできるので、あくまで手がかりとして読みます。なお、HTTP/2には理由句がないので、curlの1行目は番号だけになります。
メトリクスで数を比べる
ロードバランサには、番号を作った場所ごとの件数を見られるものがあります。AWSのALBは、CloudWatchのメトリクスを次の2つに分けています。どちらが増えているかで、調べる相手が決まります。
| メトリクス | 数える | 調べる |
|---|---|---|
| HTTPCode_ELB_5XX_Count | ロードバランサ自身が作った5xx | ロードバランサとサーバの間 |
| HTTPCode_Target_5XX_Count | 後ろのサーバが作った5xx | サーバのアプリ |
手前の機器を飛ばして、1段ずつ奥へ送る
ヘッダで分からないときは、手前の機器を飛ばしてリクエストを送ります。奥のサーバで正常なら、その手前に原因があります。奥のサーバでも同じ番号なら、原因はさらに奥にあります。
# 後ろのサーバへ直接送る例
$ curl -i \
-H 'Host: example.com' \
http://172.16.0.11/-H でHostヘッダを付けるのは、同じサーバで複数のサイトを動かしていても目的のサイトに届けるためです。サーバがプライベートIPアドレスしか持たないときは、同じネットワークの中の機器から実行します。
API Gatewayと社内プロキシの5xx
APIの前に置くゲートウェイも、中継する機器の1つです。AWSのAPI Gatewayは、Lambda関数の出力が決められた形でないと502を返します。連携先の失敗やタイムアウトには504を返します。
会社のネットワークでは、フォワードプロキシが502や504を返すことがあります。この場合、問題はサイトではなくプロキシとサイトの間にあるかもしれません。スマートフォンの回線など、プロキシを通らない経路で開けるかを比べると見分けられます。
練習問題(全6問)
正解:リクエストの
分類は
正解:403 Forbidden
誰なのかは
正解:504 Gateway Timeout
中継する
正解:301
恒久の
正解:Webサーバと
ステータス
正解:後ろの
Targetの
選んでから「採点する」を押すと、解説つきで答え合わせができます。
関連記事
おすすめの本 PR
ネットワークを初めて学ぶ人向けの入門書です。
![『[改訂新版]3分間ネットワーク基礎講座』の表紙](https://m.media-amazon.com/images/P/4774143731.09.MZZZZZZZ.jpg)
