Rails2.0でContent-Typeに勝手にcharset=utf-8をつけさせない方法

Rails2.0でコンテンツフィルタ(翻訳サイトのようなもの)を作ってるのだが、ひとつ困ったことがあった。それは、Content-Type=text/htmlとだけ書かれていて、charset指定がない応答ヘッダが帰ってきたとき、それをそのままブラウザに送って、ボディをrenderで書き出すと、RailsがContent-Typeに勝手にcharset=utf-8をつけてしまうという振る舞いに遭遇してしまったこと。

まあこれって、普通にサイト作る限りは何の支障にもならないのだろうが、コンテンツフィルタをつくっていると、元ページがContent-type=text/html だけ返してきているときに、勝手にUTF-8だとつけられてしまうと、内容はSJISだったりEUC-JPだったりで普通に文字化けしてしまうのだ。

ソースをあさったところ、ActionController::Baseになにやらdefault_charsetなるクラス属性として思いっきりutf-8って書いてあり、これはくさいぞと思って、色々ためしてみた。

actionpack-2.0.2/lib/action_controller/base.rb

    # Controls the default charset for all renders.
    @@default_charset = "utf-8"
    cattr_accessor :default_charset

結果、app/controller/application.rb(ActionController::Baseを継承してるので)に以下記述をしたところ、

  @@default_charset=nil

以下のような中途半端な応答ヘッダが飛ぶようになり、とりあえず文字化けは回避できた。

Content-Type=text/html; charset=

あまりエレガントではないが、とりあえず文字化け状態は何とかなったのでメモしておく。

(2008-5-19 追記)ましな方法

その後、上記方法だとやはり中途半端な応答ヘッダが飛ぶので、場合によっては文字化けが発生することがわかった。だから、ちゃんとソースを追ってマシな方法をみつけた。

勝手にContent-Typeを設定してほしくないコントローラに関して、以下メソッドをオーバーライドで無効化してしまう。

  def assign_default_content_type_and_charset
    #response.content_type ||= Mime::HTML
    #response.charset      ||= self.class.default_charset unless sending_file?
  end

これによって、

  • Content-Type応答ヘッダに明示的に指定したときはその通り結果が返り
  • 明示的に指定しないときは、前の例にあるような「; charset=」という余計な文字がつかずにきれいに以下のように応答が返るようになる。

Content-Type=text/html

コンテンツフィルタでなく普通のアプリ書くときは文字コード utf-8 使えばいいので、こんなこと気にしなくていいけどね^^