diff options
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | lib/net/http.rb | 29 | ||||
-rw-r--r-- | test/net/http/test_https.rb | 31 |
3 files changed, 57 insertions, 8 deletions
@@ -508,6 +508,11 @@ Net::FTP:: * Add Net::FTP#features to check available features, and Net::FTP#option to enable/disable each of them. [Feature #15964] +Net::HTTP:: + + * Add ipaddr optional parameter to Net::HTTP#start to replace the address for + TCP/IP connection [Feature #5180] + Net::IMAP:: * Add Server Name Indication (SNI) support. [Feature #15594] diff --git a/lib/net/http.rb b/lib/net/http.rb index 663b901a96..283263b323 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -571,7 +571,7 @@ module Net #:nodoc: # _opt_ :: optional hash # # _opt_ sets following values by its accessor. - # The keys are ca_file, ca_path, cert, cert_store, ciphers, + # The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers, # close_on_empty_response, key, open_timeout, read_timeout, write_timeout, ssl_timeout, # ssl_version, use_ssl, verify_callback, verify_depth and verify_mode. # If you set :use_ssl as true, you can use https and default value of @@ -590,6 +590,7 @@ module Net #:nodoc: p_addr = :ENV if arg.size < 2 port = https_default_port if !port && opt && opt[:use_ssl] http = new(address, port, p_addr, p_port, p_user, p_pass) + http.ipaddr = opt[:ipaddr] if opt[:ipaddr] if opt if opt[:use_ssl] @@ -660,6 +661,7 @@ module Net #:nodoc: def initialize(address, port = nil) @address = address @port = (port || HTTP.default_port) + @ipaddr = nil @local_host = nil @local_port = nil @curr_http_version = HTTPVersion @@ -727,6 +729,17 @@ module Net #:nodoc: attr_writer :proxy_user attr_writer :proxy_pass + # The IP address to connect to/used to connect to + def ipaddr + started? ? @socket.io.peeraddr[3] : @ipaddr + end + + # Set the IP address to connect to + def ipaddr=(addr) + raise IOError, "ipaddr value changed, but session already started" if started? + @ipaddr = addr + end + # Number of seconds to wait for the connection to open. Any number # may be used, including Floats for fractional seconds. If the HTTP # object cannot open a connection in this many seconds, it raises a @@ -934,20 +947,20 @@ module Net #:nodoc: def connect if proxy? then - conn_address = proxy_address + conn_addr = proxy_address conn_port = proxy_port else - conn_address = address + conn_addr = conn_address conn_port = port end - D "opening connection to #{conn_address}:#{conn_port}..." + D "opening connection to #{conn_addr}:#{conn_port}..." s = Timeout.timeout(@open_timeout, Net::OpenTimeout) { begin - TCPSocket.open(conn_address, conn_port, @local_host, @local_port) + TCPSocket.open(conn_addr, conn_port, @local_host, @local_port) rescue => e raise e, "Failed to open TCP connection to " + - "#{conn_address}:#{conn_port} (#{e.message})" + "#{conn_addr}:#{conn_port} (#{e.message})" end } s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) @@ -984,7 +997,7 @@ module Net #:nodoc: OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT | OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess } - D "starting SSL for #{conn_address}:#{conn_port}..." + D "starting SSL for #{conn_addr}:#{conn_port}..." s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context) s.sync_close = true # Server Name Indication (SNI) RFC 3546 @@ -1161,7 +1174,7 @@ module Net #:nodoc: # without proxy, obsolete def conn_address # :nodoc: - address() + @ipaddr || address() end def conn_port # :nodoc: diff --git a/test/net/http/test_https.rb b/test/net/http/test_https.rb index c1d486470a..9058387070 100644 --- a/test/net/http/test_https.rb +++ b/test/net/http/test_https.rb @@ -50,6 +50,37 @@ class TestNetHTTPS < Test::Unit::TestCase skip $! end + def test_get_SNI + http = Net::HTTP.new("localhost", config("port")) + http.ipaddr = config('host') + http.use_ssl = true + http.cert_store = TEST_STORE + certs = [] + http.verify_callback = Proc.new do |preverify_ok, store_ctx| + certs << store_ctx.current_cert + preverify_ok + end + http.request_get("/") {|res| + assert_equal($test_net_http_data, res.body) + } + assert_equal(CA_CERT.to_der, certs[0].to_der) + assert_equal(SERVER_CERT.to_der, certs[1].to_der) + end + + def test_get_SNI_failure + http = Net::HTTP.new("invalid_servername", config("port")) + http.ipaddr = config('host') + http.use_ssl = true + http.cert_store = TEST_STORE + certs = [] + http.verify_callback = Proc.new do |preverify_ok, store_ctx| + certs << store_ctx.current_cert + preverify_ok + end + @log_tester = lambda {|_| } + assert_raise(OpenSSL::SSL::SSLError){ http.start } + end + def test_post http = Net::HTTP.new("localhost", config("port")) http.use_ssl = true |