Webアプリケーションのサーバ通信(が失敗した編)

通信は失敗します。

そしてその理由は星の数ほどあります。

星の数ほどの失敗理由から、ほんの僅かな一覧

ホスト名が解決できない

サーバとの接続が出来ない

ポートでサービスが提供されていない

URLに該当するリソースが存在しない

応答なし

URLへのアクセスが禁止されている

サーバー内部エラー

クロスオリジン要求がブロックされた

サーバ側の定義なので詳細は省きますが、Webサービスが、サービスを提供しているサーバ以外のドメインからのリクエストを受け付ける場合、サービス提供側がAccess-Control-Allow-OriginというHTTPヘッダを使って、許可するドメインを指定します。

このヘッダが無いか、このヘッダで許可されていないドメインからのリクエストは、Webブラウザがブロックします。

XMLHttpRequestでは、何が分かるのか

残念ながら、XMLHttpRequestで障害が発生した場合、原因をあまり詳細に切り分けることはできません。

上記の一覧の例では、「(1) ホスト名が解決できない」と「(3) ポートでサービスが提供されていない」は、クロスオリジン要求(別のドメインへの通信)がブロックされた旨の理由でエラーとなります。

本来、アクセス権の問題で発生するエラーですが、サーバに接続できなかったために、アクセス権を確認できなかったことにより発生します。

また、「(2) サーバとの接続が出来ない」と「(5) 応答なし」は、どちらも同じタイムアウトです。

タイムアウト時間も設定できるのですが、コネクトタイムアウトとリクエストタイムアウトの切り分けは無いので、どちらも同じタイムアウト時間となります。

XMLHttpRequestには、いくつかのイベントハンドラが用意されているので、リスナーを登録することでそれぞれの事象に対する処理を実行できます。

XMLHttpRequestのイベントハンドラ

イベントハンドラ発生事象
loadサーバからレスポンスが返却された。正常終了とは限らないので、XMLHttpRequest.statusを確認する必要がある。
  • 正常終了(XMLHttpRequest.statusが200)

  • 「(4) URLに該当するリソースが存在しない」(XMLHttpRequest.statusが404)

  • 「(6) URLへのアクセスが禁止されている」(XMLHttpRequest.statusが403)

  • 「(7) サーバー内部エラー」(XMLHttpRequest.statusが500)

    など

error通信上の何らかのエラーが発生した。但し、サーバに接続できないようなエラーの場合、クロスオリジン要求のエラーとなってしまいます。
  • 「(1) ホスト名が解決できない」

  • 「(3) ポートでサービスが提供されていない」

  • 「(8) クロスオリジン要求がブロックされた」

    など

abortXMLHttpRequest.send()を呼び出して、レスポンスが返る前にXMLHttpRequest.abort()メソッドが呼び出された。
timeoutタイムアウトが発生した。
  • 「(2) サーバとの接続が出来ない」

  • 「(5) 応答なし」

    など

※他にもイベントハンドラは用意されていますが、今回は割愛します。

イベントハンドラを利用したサンプルソース

イベントハンドラにリスナを登録したサンプルソースです。

障害を想定したXMLHttpRequest

リダイレクト

XMLHttpRequestは、サーバがステータスコード30xを返して、Locationヘッダにリダイレクト先のURLがセットされていた場合、リダイレクトを行いその結果を返します。

リダイレクト前の情報にアクセスすることはできないため、リダイレクトが実行されたかどうかのチェックもできません。

サーバ側の仕様が明確でない場合、このあたりは結構悩まされます。

結局

色々めんどくさいことを書きましたが、結局のところ、自分自身(XMLHttpRequestを呼び出すHTML)をロードしたサーバに対してリクエストする場合、「(1) ホスト名が解決できない」とか「(2) サーバとの接続が出来ない」とか「(3) ポートでサービスが提供されていない」とか「(8) クロスオリジン要求がブロックされた」とか言うことは、余程のこと(自分自身をロードした直後にサーバがダウンしたとか)が無い限り、ありえません。

また、「(4) URLに該当するリソースが存在しない」とか「(6) URLへのアクセスが禁止されている」などということも、一度テストして問題なければそれ以降発生しえません(環境の変更がなければ、ですが)。

そして、自分自身をロードしたサーバなので、リダイレクトに関しても心配する必要は無いはずです。

自分自身をロードしたサーバとは異なるサーバにリクエストするようなケースを除けば、XMLHttpRequestは簡単で使いやすいAPIです。

どうしても、「自分自身をロードしたサーバとは異なるサーバにリクエストしたい?」。

それにはまた別のAPIが、最近用意されたんですよ、お客さん。