理系学生日記

おまえはいつまで学生気分なのか

CGI::Application で UTF-8 のテンプレートを読み込んで文字化けするときの対処

CGI::Application で Web アプリを作っているのですが,表示する画面が文字化けしました.

原因調査

CGI::Application はデフォルトのテンプレートエンジンとして HTML::Template を使いますが,HTML::Template が utf-8 で書かれたテンプレートファイルを読み込む場合に文字化けするという事象は多数報告されています.

基本的な対策としては,PerlIO 経由でテンプレートファイルを open した後,そのファイルハンドルを HTML::Template に渡すとか,ブラウザに出力する前にエンコードするフィルタをっけるとか,そういう形の対策が多いのですけど,ぼくはなかなか治らなかった.


いきなり結論になりますが,Web サーバが返す Content-Type ヘッダの charset がそもそも utf-8 ではなく ISO-8859-1 になっていたというのが原因.
そりゃ ISO-8859-1 を表示しようとしているブラウザに utf-8 のコンテンツを送ると文字化けするのも当然か.
一応 CGI が作成する HTML 中の meta タグで charset 指定してみたんですけど,うまくいきませんでした.この辺の動作はよくわからないです.

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

解決策

CGI::Application 側から,charset を utf-8 に指定したヘッダをブラウザに送れば解決しました.
下記のようなものを,CGI::Application::cgiapp_postrun あたりに仕込んでやれば良いです (cgiapp_prerun とかでも全然動くはず).

        $self->header_add('-charset', 'utf-8');

これで文字化けはしなくなりました.

今作っている部分は,form に入れた ISBN or 本のタイトルで Amazon の API を叩き結果を表示するだけのパート.これだけ作るのに一日かかってしまった.