通信は失敗します。
自分は悪くなくても、相手の不注意で簡単にエラーとなってしまいます。
そして、結果悪者になるのは、声の小さなあなたかもしれません。
明確な証拠を突きつけて「お前が悪い」と、小さな声で言えばよいのです。
そのためには、どうしてエラーとなったかを明確にする必要があります。
しかし、通信が失敗する理由は、星の数ほどあります。
URLのホスト名が間違っている。
DNSサーバがダウンしている。
URLのIPアドレスが正しくない。
相手先サーバがダウンしている。
誰かが足を引っ掛けて、ネットワークケーブルが抜けた。
Wi-Fiが接続されていない。
圏外。
URLのポート番号が正しくない。
Webサーバがダウンしている。
間違ったホストに接続している。
URLのディレクトリ名やファイル名が正しくない。
サーバに必要なディレクトリやファイルが存在しない。
サーバの負荷が高い。
URLが正しいリソースを示していない。
認証したユーザが正しくない。
Webの画面を、開発ツールなどで書き換えてリクエストしたら、ちゃんとサーバ側でチェックしていた(社内のシステムでは絶対にやらないこと、下手したら懲戒の対象になっちゃいますよ)。
サーバプログラムの不具合。
サーバ側の定義なので詳細は省きますが、Webサービスが、サービスを提供しているサーバ以外のドメインからのリクエストを受け付ける場合、サービス提供側がAccess-Control-Allow-OriginというHTTPヘッダを使って、許可するドメインを指定します。
このヘッダが無いか、このヘッダで許可されていないドメインからのリクエストは、Webブラウザがブロックします。
要求先のサービスが、異なる(許可していない)ドメインからのリクエストを受け付けない。
残念ながら、XMLHttpRequestで障害が発生した場合、原因をあまり詳細に切り分けることはできません。
上記の一覧の例では、「(1) ホスト名が解決できない」と「(3) ポートでサービスが提供されていない」は、クロスオリジン要求(別のドメインへの通信)がブロックされた旨の理由でエラーとなります。
本来、アクセス権の問題で発生するエラーですが、サーバに接続できなかったために、アクセス権を確認できなかったことにより発生します。
また、「(2) サーバとの接続が出来ない」と「(5) 応答なし」は、どちらも同じタイムアウトです。
タイムアウト時間も設定できるのですが、コネクトタイムアウトとリクエストタイムアウトの切り分けは無いので、どちらも同じタイムアウト時間となります。
XMLHttpRequestには、いくつかのイベントハンドラが用意されているので、リスナーを登録することでそれぞれの事象に対する処理を実行できます。
イベントハンドラ | 発生事象 |
---|---|
load | サーバからレスポンスが返却された。正常終了とは限らないので、XMLHttpRequest.statusを確認する必要がある。
|
error | 通信上の何らかのエラーが発生した。但し、サーバに接続できないようなエラーの場合、クロスオリジン要求のエラーとなってしまいます。
|
abort | XMLHttpRequest.send()を呼び出して、レスポンスが返る前にXMLHttpRequest.abort()メソッドが呼び出された。 |
timeout | タイムアウトが発生した。
|
※他にもイベントハンドラは用意されていますが、今回は割愛します。
イベントハンドラにリスナを登録し、障害を想定したXMLHttpRequestのサンプルソースです。
XMLHttpRequestは、サーバがステータスコード30xを返して、Locationヘッダにリダイレクト先のURLがセットされていた場合、リダイレクトを行いその結果を返します。
リダイレクト前の情報にアクセスすることはできないため、リダイレクトが実行されたかどうかのチェックもできません。
サーバ側の仕様が明確でない場合、このあたりは結構悩まされます。
色々めんどくさいことを書きましたが、結局のところ、自分自身(XMLHttpRequestを呼び出すHTML)をロードしたサーバに対してリクエストする場合、「(1) ホスト名が解決できない」とか「(2) サーバとの接続が出来ない」とか「(3) ポートでサービスが提供されていない」とか「(8) クロスオリジン要求がブロックされた」とか言うことは、余程のこと(自分自身をロードした直後にサーバがダウンしたとか)が無い限り、ありえません。
また、「(4) URLに該当するリソースが存在しない」とか「(6) URLへのアクセスが禁止されている」などということも、一度テストして問題なければそれ以降発生しえません(環境の変更がなければ、ですが)。
そして、自分自身をロードしたサーバなので、リダイレクトに関しても心配する必要は無いはずです。
自分自身をロードしたサーバとは異なるサーバにリクエストするようなケースを除けば、XMLHttpRequestは簡単で使いやすいAPIです。
どうしても、「自分自身をロードしたサーバとは異なるサーバにリクエストしたい?」。
それにはまた別のAPIが、最近用意されたんですよ、お客さん。