XMLHttpRequestオブジェクトでリダイレクトをハンドリングする方法

以前に、同じタイトルのエントリを書いたのですが、それよりもスマートなやり方がわかったので、書いておきます。

やりたいことについては前のエントリで書いたとおり。

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

前のエントリでは、XMLHttpRequestでレスポンスヘッダが使えることに着目して、"Content-Type"ヘッダが"text/html"だったらページを強制的に遷移させる方法でした。しかし、この方法は「"Content-Type"ヘッダが"text/html"である正常なレスポンス」があったら使えません。そこで以下の方法を思いつきました。4. および 6. のところが今回紹介する方法になります。

  1. XMLHttpRequestで送ったリクエストが、サーバで認証エラー(セッションタイムアウトなど)となる
  2. このときサーバは認証エラー(=401)を返すのではなく、ログインページへのリダイレクトを返す
  3. クライアント(XMLHttpRequest)は、リダイレクト応答をうけとり、自動的にリダイレクト先を追跡する
  4. ログインページでは、レスポンスヘッダに "AjaxRedirect: /Login.jsp" を追加する
  5. 結果、クライアントはログインページのHTMLを取得する(このときステータスコード=200)
  6. クラインアンは、レスポンスヘッダをチェックし、"AjaxRedirect" ヘッダが設定されているので、その値のURLを追跡する

以上で、XMLHttpRequestを使ったリダイレクトの完成。サンプルコードも載せておきます。

<%
response.setHeader("AjaxRedirect", request.getContextPath() + "/Login.jsp");
%>
httpRequest.onreadystatechange = function() {
  if (httpRequest.readyState == 4 && httpRequest.status == 200) {
    var redctUrl = httpRequest.getResponseHeader("AjaxRedirect");
    if (redctUrl != null) 
      // リダイレクトURLが設定されていれば追跡
      window.location.href = redctUrl;