Hatena::ブログ(Diary)

unnecessary words このページをアンテナに追加 RSSフィード

2008-02-05

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でも動いております。

maraiguemaraigue 2008/03/26 02:05 同じ状況で迷っておりました。
そのまま使ってもうまくいかなかったのですが、(Windows環境なので)StringIO.new(res.body)をStringIO.new(res.body, ”rb”)としたらうまくいきました。
ありがとうございます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証