WEBRickプロキシでgzipに対応する

これの続き。
IEでは動くWEBRickのフィルタプロキシが、Firefoxでは動きません。
原因はFirefoxgzipが有効な為。両者のヘッダは以下のようになっています。

#IE6
{"cache-control"=>"private",
 "connection"=>"close",
 "via"=>"1.1 s33:8080",
 "content-type"=>"text/html; charset=UTF-8",
 "date"=>"Tue, 05 Feb 2008 05:00:40 GMT",
 "server"=>"gws",
 "proxy-connection"=>"close"}

#Firefox2
{"cache-control"=>"private",
 "connection"=>"close",
 "via"=>"1.1 s33:8080",
 "content-type"=>"text/html; charset=UTF-8",
 "date"=>"Tue, 05 Feb 2008 04:59:38 GMT",
 "content-encoding"=>"gzip",
 "server"=>"gws",
 "proxy-connection"=>"close",
 "content-length"=>"2887"}

というわけで、gzipで圧縮されているものについては解凍してからフィルタ処理を行うように改良しました。

#!/usr/bin/ruby -Ku
require 'webrick'
require 'webrick/httpproxy'
require 'kconv'
require 'stringio'
require 'zlib'

handler = Proc.new() do |req, res|
  if res['content-type'] =~ %r!text/html!
    body = res.body
    if res.header["content-encoding"] == "gzip"
      Zlib::GzipReader.wrap(StringIO.new(res.body)){|gz| body = gz.read}
      res.header.delete("content-encoding")
      res.header.delete("content-length")
    end
    utf_str = body.toutf8
    utf_str.gsub!(//, 'にょ。')
    code = Kconv.guess(body)
    res.body = utf_str.kconv(code, Kconv::UTF8)
  end
end

config = {
  :BindAddress => '0.0.0.0',
  :Port => 8080,
  :ProxyContentHandler => handler,
}

s = WEBrick::HTTPProxyServer.new(config)
[:INT, :TERM].each{|sig| Signal.trap(sig){s.shutdown}}
s.start

Zlibライブラリでgzipの解凍ができますが引数にioが必要(Zlib::GzipReader)です。StringIOで、Stringにファイルのふりをさせます。ダックタイピング万歳。
フィルタ処理後、再圧縮はせずに送り出します。content-encodingは削除。content-lengthは再計算した方がいいような気もするけど、ひとまず削除。
これでFirefoxでも動いております。