前回までのあらすじ
以前VolleyでCookieとUserAgentをまとめていじりたいとは言ったのだけれど、どうにもcookieの扱いが無理やりすぎてコレジャナイ感があった。実際"responseを拾えばSet-Cookieを回収できる"とは言ったものの、単純なString扱いなので例えばDomainごとに制御したりとかができないのだ。
Volleyの同じQueueで自分のAPIとTwitter両方ともつついたりしてると、双方に双方のCookieを流し込むことになる。そんなの気持ち悪い!なんとかしたい!(というかセキュリティ的にアカン)
HurlStack、あるいはHttpURLConnectionをちゃんと考える
そもそもVolleyを使う為に仕方なくHurlStackを使ってる、という意識だったので理解が薄すぎた。どう考えても標準でCookieを扱う仕組みがあるべきだし、あるだろう。HurlStack方面でそれを調べて見る。
HurlStack。とはいえこいつの中ではHttpURLConnectionを使っているにすぎない。そしてこれにはきちんとCookieを操作するための標準的な仕組みが存在する。それが CookieHandler
やCookieManager
だ。
CookieManagerを使えばCookieStoreが取得できる。中身はHttpCookieというのが詰まっていて、もうこれはほぼゴールだ。getName()やgetValue()だけじゃない、getDomain()もできちゃったりしてやりたい放題だ。これに任せよう。
きちんと設定してあげればVolley以外でもHttpURLConnectionを使っている箇所すべてにCookieが染み渡るのも素晴らしい。
RequestQueueに入れてみる
以上の点を踏まえ、前回同様RequestQueueをこう書き換えてみた
// CookieManagerを作ってDefaultに設定
final CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
// Volleyのリクエストキューを生成
RequestQueue mRequestQueue = Volley.newRequestQueue(getApplicationContext(), new HurlStack(){
@Override
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError {
Map newHeaders = new HashMap();
newHeaders.putAll(additionalHeaders);
// セッション維持のためcookieとUserAgentを設定する
newHeaders.put("User-Agent", "ユーザーエージェント");
// 実際はoldCookieはどこからともなく持ってきてStoreに登録する
CookieStore store = cookieManager.getCookieStore();
HttpCookie oldCookie = new HttpCookie("クッキーのname", "クッキーのvalue");
store.add(URI.create("domain"), oldCookie);
// responseを待ってCookieを回収する
HttpResponse response = super.performRequest(request, newHeaders);
// cookieの回収
List<HttpCookie> cookies = store.getCookies();
if (cookies.size() > 0) {
// あればクッキーを保存
// cookies.get(0)とかをどうにかこうにか保存します
}
return response;
}
});
これならたぶん有効期限とかもよしなに処理してくれるし、絶対こっちのほうが健全だと思った。
参考
どうしてJaveでCookieが取得できないんだろう?
もうだいぶ昔の話で表題のバグはなおってるっぽいけれど、中の動きがよくわかった。(気がする)