зеркало из https://github.com/github/ruby.git
[ruby/open-uri] Added SimpleHTTPProxyServer by TCPServer
https://github.com/ruby/open-uri/commit/ad47529306
This commit is contained in:
Родитель
a574e290c5
Коммит
debcf108fa
|
@ -2,21 +2,10 @@
|
|||
require 'test/unit'
|
||||
require 'open-uri'
|
||||
require_relative 'utils'
|
||||
require 'webrick'
|
||||
require 'webrick/httpproxy'
|
||||
begin
|
||||
require 'zlib'
|
||||
rescue LoadError
|
||||
end
|
||||
|
||||
class TestOpenURIProxy < Test::Unit::TestCase
|
||||
include TestOpenURIUtils
|
||||
|
||||
NullLog = Object.new
|
||||
def NullLog.<<(arg)
|
||||
#puts arg if / INFO / !~ arg
|
||||
end
|
||||
|
||||
def with_env(h)
|
||||
begin
|
||||
old = {}
|
||||
|
@ -41,18 +30,12 @@ class TestOpenURIProxy < Test::Unit::TestCase
|
|||
def test_proxy
|
||||
with_http {|srv, url|
|
||||
proxy_log = StringIO.new(''.dup)
|
||||
proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
|
||||
proxy_auth_log = ''.dup
|
||||
proxy = WEBrick::HTTPProxyServer.new({
|
||||
:ServerType => Thread,
|
||||
:Logger => proxy_logger,
|
||||
:AccessLog => [[NullLog, ""]],
|
||||
:ProxyAuthProc => lambda {|req, res|
|
||||
proxy_host = '127.0.0.1'
|
||||
proxy = SimpleHTTPProxyServer.new(proxy_host, 0, lambda {|req, res|
|
||||
proxy_auth_log << req.request_line
|
||||
},
|
||||
:BindAddress => '127.0.0.1',
|
||||
:Port => 0})
|
||||
_, proxy_port, _, proxy_host = proxy.listeners[0].addr
|
||||
}, proxy_log)
|
||||
proxy_port = proxy.instance_variable_get(:@server).addr[1]
|
||||
proxy_url = "http://#{proxy_host}:#{proxy_port}/"
|
||||
begin
|
||||
proxy_thread = proxy.start
|
||||
|
@ -95,21 +78,15 @@ class TestOpenURIProxy < Test::Unit::TestCase
|
|||
def test_proxy_http_basic_authentication_failure
|
||||
with_http {|srv, url|
|
||||
proxy_log = StringIO.new(''.dup)
|
||||
proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
|
||||
proxy_auth_log = ''.dup
|
||||
proxy = WEBrick::HTTPProxyServer.new({
|
||||
:ServerType => Thread,
|
||||
:Logger => proxy_logger,
|
||||
:AccessLog => [[NullLog, ""]],
|
||||
:ProxyAuthProc => lambda {|req, res|
|
||||
proxy_host = '127.0.0.1'
|
||||
proxy = SimpleHTTPProxyServer.new(proxy_host, 0, lambda {|req, res|
|
||||
proxy_auth_log << req.request_line
|
||||
if req["Proxy-Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
|
||||
raise WEBrick::HTTPStatus::ProxyAuthenticationRequired
|
||||
raise ProxyAuthenticationRequired
|
||||
end
|
||||
},
|
||||
:BindAddress => '127.0.0.1',
|
||||
:Port => 0})
|
||||
_, proxy_port, _, proxy_host = proxy.listeners[0].addr
|
||||
}, proxy_log)
|
||||
proxy_port = proxy.instance_variable_get(:@server).addr[1]
|
||||
proxy_url = "http://#{proxy_host}:#{proxy_port}/"
|
||||
begin
|
||||
th = proxy.start
|
||||
|
@ -121,28 +98,22 @@ class TestOpenURIProxy < Test::Unit::TestCase
|
|||
proxy.shutdown
|
||||
th.join
|
||||
end
|
||||
assert_match(/ERROR WEBrick::HTTPStatus::ProxyAuthenticationRequired/, proxy_log.string)
|
||||
assert_match(/ERROR ProxyAuthenticationRequired/, proxy_log.string)
|
||||
}
|
||||
end
|
||||
|
||||
def test_proxy_http_basic_authentication_success
|
||||
with_http {|srv, url|
|
||||
proxy_log = StringIO.new(''.dup)
|
||||
proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
|
||||
proxy_auth_log = ''.dup
|
||||
proxy = WEBrick::HTTPProxyServer.new({
|
||||
:ServerType => Thread,
|
||||
:Logger => proxy_logger,
|
||||
:AccessLog => [[NullLog, ""]],
|
||||
:ProxyAuthProc => lambda {|req, res|
|
||||
proxy_host = '127.0.0.1'
|
||||
proxy = SimpleHTTPProxyServer.new(proxy_host, 0, lambda {|req, res|
|
||||
proxy_auth_log << req.request_line
|
||||
if req["Proxy-Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
|
||||
raise WEBrick::HTTPStatus::ProxyAuthenticationRequired
|
||||
raise ProxyAuthenticationRequired
|
||||
end
|
||||
},
|
||||
:BindAddress => '127.0.0.1',
|
||||
:Port => 0})
|
||||
_, proxy_port, _, proxy_host = proxy.listeners[0].addr
|
||||
}, proxy_log)
|
||||
proxy_port = proxy.instance_variable_get(:@server).addr[1]
|
||||
proxy_url = "http://#{proxy_host}:#{proxy_port}/"
|
||||
begin
|
||||
th = proxy.start
|
||||
|
@ -169,21 +140,15 @@ class TestOpenURIProxy < Test::Unit::TestCase
|
|||
def test_authenticated_proxy_http_basic_authentication_success
|
||||
with_http {|srv, url|
|
||||
proxy_log = StringIO.new(''.dup)
|
||||
proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
|
||||
proxy_auth_log = ''.dup
|
||||
proxy = WEBrick::HTTPProxyServer.new({
|
||||
:ServerType => Thread,
|
||||
:Logger => proxy_logger,
|
||||
:AccessLog => [[NullLog, ""]],
|
||||
:ProxyAuthProc => lambda {|req, res|
|
||||
proxy_host = '127.0.0.1'
|
||||
proxy = SimpleHTTPProxyServer.new(proxy_host, 0, lambda {|req, res|
|
||||
proxy_auth_log << req.request_line
|
||||
if req["Proxy-Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
|
||||
raise WEBrick::HTTPStatus::ProxyAuthenticationRequired
|
||||
raise ProxyAuthenticationRequired
|
||||
end
|
||||
},
|
||||
:BindAddress => '127.0.0.1',
|
||||
:Port => 0})
|
||||
_, proxy_port, _, proxy_host = proxy.listeners[0].addr
|
||||
}, proxy_log)
|
||||
proxy_port = proxy.instance_variable_get(:@server).addr[1]
|
||||
proxy_url = "http://user:pass@#{proxy_host}:#{proxy_port}/"
|
||||
begin
|
||||
th = proxy.start
|
||||
|
|
|
@ -148,8 +148,83 @@ class SimpleHTTPServer
|
|||
end
|
||||
end
|
||||
|
||||
class SimpleHTTPProxyServer
|
||||
def initialize(host, port, auth_proc = nil, log)
|
||||
@server = TCPServer.new(host, port)
|
||||
@auth_proc = auth_proc
|
||||
@log = log
|
||||
end
|
||||
|
||||
def start
|
||||
@thread = Thread.new do
|
||||
loop do
|
||||
client = @server.accept
|
||||
request_line = client.gets
|
||||
headers = {}
|
||||
while (line = client.gets) && (line != "\r\n")
|
||||
key, value = line.chomp.split(/:\s*/, 2)
|
||||
headers[key] = value
|
||||
end
|
||||
next unless request_line
|
||||
|
||||
method, path, _ = request_line.split(' ')
|
||||
handle_request(client, method, path, request_line, headers)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def shutdown
|
||||
@thread.kill
|
||||
@server.close
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_request(client, method, path, request_line, headers)
|
||||
if @auth_proc
|
||||
req = Request.new(method, path, request_line, headers)
|
||||
res = Struct.new(:body, :status).new("", 200)
|
||||
@auth_proc.call(req, res)
|
||||
if res.status != 200
|
||||
client.print "HTTP/1.1 #{res.status}\r\nContent-Type: text/plain\r\n\r\n#{res.body}"
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
uri = URI(path)
|
||||
proxy_request(uri, client)
|
||||
rescue TestOpenURIProxy::ProxyAuthenticationRequired
|
||||
@log << "ERROR ProxyAuthenticationRequired"
|
||||
client.print "HTTP/1.1 407 Proxy Authentication Required\r\nContent-Length: 0\r\n\r\n"
|
||||
ensure
|
||||
client.close
|
||||
end
|
||||
|
||||
def proxy_request(uri, client)
|
||||
Net::HTTP.start(uri.host, uri.port) do |http|
|
||||
response = http.get(uri.path)
|
||||
client.print "HTTP/1.1 #{response.code}\r\nContent-Type: #{response.content_type}\r\n\r\n#{response.body}"
|
||||
end
|
||||
end
|
||||
|
||||
class Request
|
||||
attr_reader :method, :path, :request_line, :headers
|
||||
def initialize(method, path, request_line, headers)
|
||||
@method = method
|
||||
@path = path
|
||||
@request_line = request_line
|
||||
@headers = headers
|
||||
end
|
||||
|
||||
def [](key)
|
||||
@headers[key]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module TestOpenURIUtils
|
||||
class Unauthorized < StandardError; end
|
||||
class ProxyAuthenticationRequired < StandardError; end
|
||||
|
||||
def with_http(log_tester=lambda {|log| assert_equal([], log) })
|
||||
log = []
|
||||
|
|
Загрузка…
Ссылка в новой задаче