# $kNotwork: toyproxy.rb,v 1.5 2002/01/07 15:49:10 gotoken Exp $ require "webrick" require "net/http" class HTTPProxyServer < WEBrick::HTTPServer class HTTPProxyServlet < WEBrick::HTTPServlet::AbstractServlet include Net include WEBrick HTTP::version_1_2 if RUBY_VERSION =~ /^1\.6/ def service(req, res) res.http_version = "1.0" method_name = req.request_method scheme, host, port, path, header = preprocess(req,res) begin http = HTTP.new(host, port) ################################## these issues are http.open_timeout = 30 # secs # necessary (maybe bacause http.read_timeout = 60 # secs # Ruby's bug, but why?) ################################## case method_name when "GET" response = http.get(path, header) res.body = response.body when "POST" response = http.post(path, req.body, header) res.body = response.body when "HEAD" response = http.head(path, header) else raise HTTPStatus::MethodNotAllowed, "unsupported method `#{req.request_method}'." end rescue SocketError, Errno::ECONNREFUSED => err raise HTTPStatus::ServiceUnavailable, err.message end response.each do |name,value| res[name] = value @logger.debug ">#{name}: #{value}" end res['Proxy-Connection'] = 'closed' res.status = response.code.to_i end private def preprocess(req,res) if @config[:AuthProc] HTTPAuth::proxy_basic_auth(req,res,"hogehoge",&@config[:AuthProc]) end req.header.delete("proxy-authorization") if %r!^/! =~ req.request_uri.to_s raise HTTPStatus::BadRequest, req.request_uri.to_s end uri = req.request_uri scheme = uri.scheme host = uri.host port = uri.port path = uri.path query = uri.query query[0,0] = "?" if query # create Net::HTTP compatible header header = Hash.new req.each{|k,v| header[k] = v} req.raw_header.each{|line| @logger.debug '<'+line.chomp} [scheme, host, port, "#{path}#{query}", header] end def initialize(config, *options) super @logger = @config[:Logger] end end def initialize(config, default = WEBrick::Config::HTTP) super mount("/", HTTPProxyServlet) end end if __FILE__ == $0 require 'getopts' include WEBrick getopts("d", "port:8128", "logfile:") $-d = $OPT_d log = $OPT_logfile ? open($OPT_logfile, "a") : STDERR passwd = {"user" => "passwd"} config = { :Port => $OPT_port, :Logger => Log.new(log, ($OPT_d ? Log::DEBUG : Log::INFO)), :AuthProc => lambda{|user,pass| user and passwd[user] == pass}, } proxy = HTTPProxyServer.new(config) trap('INT'){ proxy.shutdown } trap('TERM'){ proxy.shutdown } proxy.start end