Hatena::ブログ(Diary)

on the center line.

2008-05-13

XMLHttpRequestオブジェクトでRedirectをハンドリングするには?(リダイレクトを拾う方法)

| 21:45

XMLHttpRequestオブジェクトから送信したリクエストに対し、サーバリダイレクト応答(ステータスコード=302)を返したときのハンドリングってどうやればいいんだろうか?と悩んだのでその記録。

解決したかったのは、以下のような問題。

  1. XMLHttpRequestで送ったリクエストが、サーバで認証エラー(セッションタイムアウトなど)となる
  2. このときサーバは認証エラー(=401)を返すのではなく、ログインページへのリダイレクトを返す
  3. クライアントXMLHttpRequest)は、リダイレクト応答をうけとり、自動的にリダイレクト先を追跡する
  4. 結果、クライアントログインページのHTMLを取得する(このときステータスコード=200)
  5. しかし、そもそもクライアントJSON形式のデータを期待しているためスクリプトエラーとなる

調べてみたところ、XMLHttpRequestリダイレクト応答をうけとると何事もなかったかのようにリダイレクト先にリクエストを送信してしまうようだ。そのため、クライアント側ではリダイレクトされたかどうかが判別できない(ステータスコードは常に200)。これでは困るのでステータスコード以外について調べてみたところ、レスポンスヘッダーの取得はできるようだ。これは都合がいい。

というのは、今回問題が発生したWebアプリではXMLHttpRequestのレスポンスは『必ず』JSON形式(=text/plain)としている。なので、text/htmlのレスポンスが返されたら、それはリダイレクトとみなすことができる。

完全な解決策とはいえないけど、以下のコードで問題解決。

httpRequest.onreadystatechange = function() {
  if (httpRequest.readyState == 4 && httpRequest.status == 200) {
    var cType = httpRequest.getResponseHeader("Content-Type");
    if (cType.toLowerCase().indexOf("text/plain") == -1) 
      window.location.href = url;                                             ← ここで認証エラーとなったリクエストを再送→リダイレクト
    // 以下、省略
トラックバック - http://d.hatena.ne.jp/kenpoco/20080513/1210682706
Connection: close