diff --git a/ChangeLog b/ChangeLog index de24a54cdb..d5a17804ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Jul 25 09:05:38 2012 Eric Hodel + + * lib/net/http.rb: Added SSL session reuse across connections for a + single instance to speed up connection. [Feature #5341] + * NEWS: ditto + * test/net/http/test_https.rb: Tests for #5341 + Wed Jul 25 06:54:24 2012 Eric Hodel * doc/re.rdoc: Fix spelling diff --git a/NEWS b/NEWS index 85add229de..ce1dc8be9f 100644 --- a/NEWS +++ b/NEWS @@ -89,6 +89,8 @@ with all sufficient information, see the ChangeLog file. variable. See Net::HTTP::new for details. * gzip and deflate compression are now requested for all requests by default. See Net::HTTP for details. + * SSL sessions are now reused across connections for a single instance. + This speeds up connection by using a previously negotiated session. * new methods: * Net::HTTP#local_host * Net::HTTP#local_host= diff --git a/lib/net/http.rb b/lib/net/http.rb index 357c41fbd7..0381099a07 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -649,6 +649,7 @@ module Net #:nodoc: @use_ssl = false @ssl_context = nil + @ssl_session = nil @enable_post_connection_check = true @sspi_enabled = false SSL_IVNAMES.each do |ivname| @@ -903,12 +904,14 @@ module Net #:nodoc: @socket.write(buf) HTTPResponse.read_new(@socket).value end + s.session = @ssl_session if @ssl_session # Server Name Indication (SNI) RFC 3546 s.hostname = @address if s.respond_to? :hostname= Timeout.timeout(@open_timeout, Net::OpenTimeout) { s.connect } if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE s.post_connection_check(@address) end + @ssl_session = s.session rescue => exception D "Conn close because of connect error #{exception}" @socket.close if @socket and not @socket.closed? diff --git a/test/net/http/test_https.rb b/test/net/http/test_https.rb index 3b843b140f..2a42db7209 100644 --- a/test/net/http/test_https.rb +++ b/test/net/http/test_https.rb @@ -59,6 +59,29 @@ class TestNetHTTPS < Test::Unit::TestCase skip $! end + def test_session_reuse + http = Net::HTTP.new("localhost", config("port")) + http.use_ssl = true + http.verify_callback = Proc.new do |preverify_ok, store_ctx| + store_ctx.current_cert.to_der == config('ssl_certificate').to_der + end + + http.start + http.get("/") + http.finish + + http.start + http.get("/") + http.finish # three times due to possible bug in OpenSSL 0.9.8 + + http.start + http.get("/") + + socket = http.instance_variable_get(:@socket).io + + assert socket.session_reused? + end + if ENV["RUBY_OPENSSL_TEST_ALL"] def test_verify http = Net::HTTP.new("ssl.netlab.jp", 443)