Index: lib/net/http.rb =================================================================== --- lib/net/http.rb (revision 35970) +++ lib/net/http.rb (working copy) @@ -277,6 +277,12 @@ module Net #:nodoc: # # always connect to your.proxy.addr:8080 # } # + # You may also create a proxy from the HTTP_PROXY environment variable: + # + # Net::HTTP::Proxy(:ENV).start('www.example.com') { |http| + # # always connect through ENV['HTTP_PROXY'] + # } + # # Net::HTTP::Proxy returns a Net::HTTP instance when proxy_addr is nil so # there is no need for conditional code. # @@ -882,6 +888,10 @@ module Net #:nodoc: # the port to use to access the proxy, and a username and password # if authorization is required to use the proxy. # + # You may also supply :ENV to read proxy settings from the + # environment variables +HTTP_PROXY+, +HTTP_PROXY_USER+ and + # +HTTP_PROXY_PASS+ (or their lowercase equivalents). + # # You can replace any use of the Net::HTTP class with use of the # proxy class created. # @@ -907,15 +917,24 @@ module Net #:nodoc: # # and password # } # - # Note that net/http does not use the HTTP_PROXY environment variable. - # If you want to use a proxy, you must set it explicitly. - # def HTTP.Proxy(p_addr, p_port = nil, p_user = nil, p_pass = nil) return self unless p_addr - delta = ProxyDelta - proxyclass = Class.new(self) - proxyclass.module_eval { - include delta + + if p_addr == :ENV then + env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY'] + + return self unless env_proxy + + env_proxy =~ /:([^\]]+)\z/ # handle IPv6 address like [::1]:8000 + p_addr = $` || env_proxy + p_port = $1.to_i if $1 + + p_user = ENV['http_proxy_user'] || ENV['HTTP_PROXY_USER'] + p_pass = ENV['http_proxy_pass'] || ENV['HTTP_PROXY_PASS'] + end + + Class.new(self) { + include Net::HTTP::ProxyDelta # with proxy @is_proxy_class = true @proxy_address = p_addr @@ -923,7 +942,6 @@ module Net #:nodoc: @proxy_user = p_user @proxy_pass = p_pass } - proxyclass end class << HTTP Index: test/net/http/test_http.rb =================================================================== --- test/net/http/test_http.rb (revision 35969) +++ test/net/http/test_http.rb (working copy) @@ -5,6 +5,128 @@ require 'net/http' require 'stringio' require_relative 'utils' +class TestNetHTTP < Test::Unit::TestCase + + def test_class_Proxy + no_proxy_class = Net::HTTP.Proxy nil + + assert_equal Net::HTTP, no_proxy_class + + proxy_class = Net::HTTP.Proxy 'proxy.example', 8000, 'user', 'pass' + + refute_equal Net::HTTP, proxy_class + + assert_operator proxy_class, :<, Net::HTTP + + assert_equal 'proxy.example', proxy_class.proxy_address + assert_equal 8000, proxy_class.proxy_port + assert_equal 'user', proxy_class.proxy_user + assert_equal 'pass', proxy_class.proxy_pass + end + + def test_class_Proxy_from_ENV + clean_http_proxy_env do + ENV['HTTP_PROXY'] = 'proxy.example:8000' + ENV['HTTP_PROXY_USER'] = 'user' + ENV['HTTP_PROXY_PASS'] = 'pass' + + proxy_class = Net::HTTP.Proxy :ENV + + refute_equal Net::HTTP, proxy_class + + assert_operator proxy_class, :<, Net::HTTP + + assert_equal 'proxy.example', proxy_class.proxy_address + assert_equal 8000, proxy_class.proxy_port + assert_equal 'user', proxy_class.proxy_user + assert_equal 'pass', proxy_class.proxy_pass + end + end + + def test_class_Proxy_from_ENV_ipv6 + clean_http_proxy_env do + ENV['HTTP_PROXY'] = '[::1]:8000' + + proxy_class = Net::HTTP.Proxy :ENV + + refute_equal Net::HTTP, proxy_class + + assert_operator proxy_class, :<, Net::HTTP + + assert_equal '[::1]', proxy_class.proxy_address + assert_equal 8000, proxy_class.proxy_port + assert_nil proxy_class.proxy_user + assert_nil proxy_class.proxy_pass + end + end + + def test_class_Proxy_from_ENV_lowercase + clean_http_proxy_env do + ENV['http_proxy'] = 'proxy.example:8000' + ENV['http_proxy_user'] = 'user' + ENV['http_proxy_pass'] = 'pass' + + proxy_class = Net::HTTP.Proxy :ENV + + refute_equal Net::HTTP, proxy_class + + assert_operator proxy_class, :<, Net::HTTP + + assert_equal 'proxy.example', proxy_class.proxy_address + assert_equal 8000, proxy_class.proxy_port + assert_equal 'user', proxy_class.proxy_user + assert_equal 'pass', proxy_class.proxy_pass + end + end + + def test_class_Proxy_from_ENV_none + clean_http_proxy_env do + no_proxy_class = Net::HTTP.Proxy :ENV + + assert_equal Net::HTTP, no_proxy_class + end + end + + def test_class_Proxy_from_ENV_no_port + clean_http_proxy_env do + ENV['HTTP_PROXY'] = 'proxy.example' + + proxy_class = Net::HTTP.Proxy :ENV + + refute_equal Net::HTTP, proxy_class + + assert_operator proxy_class, :<, Net::HTTP + + assert_equal 'proxy.example', proxy_class.proxy_address + assert_equal 80, proxy_class.proxy_port + assert_nil proxy_class.proxy_user + assert_nil proxy_class.proxy_pass + end + end + + def clean_http_proxy_env + orig = { + 'HTTP_PROXY' => ENV['HTTP_PROXY'], + 'http_proxy' => ENV['HTTP_PROXY'], + 'HTTP_PROXY_USER' => ENV['HTTP_PROXY_USER'], + 'http_proxy_user' => ENV['http_proxy_user'], + 'HTTP_PROXY_PASS' => ENV['HTTP_PROXY_PASS'], + 'http_proxy_pass' => ENV['http_proxy_pass'], + } + + orig.each_key do |key| + ENV.delete key + end + + yield + ensure + orig.each do |key, value| + ENV[key] = value + end + end + +end + module TestNetHTTP_version_1_1_methods def test_s_get