2013年9月3日火曜日

Dispatch(reboot)で文字化けが起きた時の対応

今日これで30分ぐらい無駄にしたので忘れる前にメモ。

概要


Dispatchを使ってHTTPクライアントを作ると、稀に文字化けすることがあるので、その原因と対策をまとめる。
ちなみにDispatchはAsyncHttpClientを内部で使っていて、今回の話題はAsyncHttpClientの領域にも少し踏み込む。

原因と解決方針


文字化けの原因はHTTPクライアントにはよくある話で、HTTPレスポンスヘッダのContent-Typeにcharsetがセットされていない(または間違っている)のが原因。
Bodyバイト列をStringに変換するときにContent-Typeのcharsetを用いるのだが、デフォルトではISO-8859-1が使われるため、charset未設定のヘッダが来ると、bodyの文字コードが例えUTF8であっても化けてしまう。

で、これの解決方法として、ResponseFilterを使う。
ResponseFilterはAsyncHttpClient側の機能で、bodyの解析前に処理を挟むことができる。これを用いて、ヘッダのContent-Typeにcharsetを書き込んでしまえば良い。

DispatchからResponseFilterを挟む


あとは実際にコードを書くだけだが、今回はDispatchからの利用なのでDispatchのAPIからResponseFilterを挟む必要がある。実際にコードを見たほうが早いだろう。



Dispatchで提供されるデフォルトのHttpはconfigureメソッドを持っており、これにAsyncHttpClientConfig.Builderをいじる関数を渡してやることで、HTTPクライアントの挙動を制御することができる。今回はaddResponseFilterを使ってResponseFilterを挟んでやろうと言うわけだ。ResponseFilterの実装はcharset無しのContent-Typeが渡ってきたらcharset付きで上書きしてやろうというもの。Scalaの感覚で「Filter」というとFilterContextを受け取って新しいFilterContextを生成する実装をしたくなるが、ここでは単純にmutableなオブジェクトの操作でOK。

この例では"text/html"の時だけUTF-8を指定しているだけだが、必要に応じて実装を書き換えてやれば良い。

参考


Http.configureについてはこちら、AsyncHttpClientConfig.Builderについてはこちら、ResponseFilterについてはこちらを参照。

0 件のコメント:

コメントを投稿