WEBRickプロキシでgzipに対応する
これの続き。
IEでは動くWEBRickのフィルタプロキシが、Firefoxでは動きません。
原因はFirefoxでgzipが有効な為。両者のヘッダは以下のようになっています。
#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でも動いております。