2015-01-18

XHR({mozSystem: true})がマジで使えない件

XHR (XMLHttpRequest) 自体は、CORS (Cross-Origin Resource Sharing) をサポートしないと自分のドメイン以外へのXHRのリクエストに対してレスポンスヘッダーとかの値を取ることはできない。そのためFirefox OSではmozSystemというオプションを用意して、CORS対象でないサイトへのリクエストであってもXHRが使えるようにはなっている (SystemXHRの権限を与える必要あり)。

また、XHRは302などのリダイレクションに対しては、自動でリダイレクト処理を行う。

CORSが使える環境においては、XHR.withCredentials = true にするとCookieとかも扱えるようになる。CORSじゃない環境 (mozSystem:true) の時はCookieとかは自動的には送らない。

XHRはこんな感じで動作するだが、この前提において、こんなケースにぶち当たった。

POST /abc
Host: example.com
Content-Type: application/x-www-form-urlencoded
Cookie: SESSIONID=ABC

というリクエストをとあるサーバーに投げると

302 redirect HTTP/1.1
Location: https://example.com/def
Set-Cookie: cookie=ABC <----(A)

と返してくるから、XHRは自動的にリダイレクト処理をするので、

GET /def
Host: example.com
Cookie: SESSIONID=ABC

と送るわけだ。ここで重要なのは (A) でSet-Cookieした値は、リダイレクト後のGETには入らないということ (mozSystem: trueだから)。そのCookieがWebサーバー側は必要としてたようで、以下のように返してきた。

404 Not Found HTTP/1.1
Host: example.com

(A) の値さえ取得できれば、自分でリダイレクト処理をすればいいんだけど、当然ここから、(A) を取得する方法なんて存在しないようで。。。XHRでリダイレクトを止めたいという話はstackoverflowでもwell-knownな質問で、答えは「不可能」。

一瞬mozTCPSocketを使って簡易HTTPクライアントを作ろうかと思ったけど、そもそもHTTPSなサイトなんだよねということで諦めた。このXHR({mozSystem: true})自体はちょっと凝ったことはできないよねってこと。そもそもFetch APIが来てればこんな悩みもしなかったのにって話でした。

(後でmozSystem:trueの場合でいいからリダイレクトを止めるオプション作りやがれバグはファイルしておくが)

0 件のコメント: