mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-12-07 00:00:31 -05:00
ssl: support session resumption on reconnections with same session
when connections get reset due to max number of requests being reached,
the same TLS session is going to be reused, as long as it's valid.
This change is ported from the same feature in net-http, including [the
tls 1.3
improvements](ddf5c52b5f)
This commit is contained in:
parent
f03d9bb648
commit
ef2f0cc998
@ -42,7 +42,7 @@ module HTTPX
|
||||
|
||||
def_delegator :@write_buffer, :empty?
|
||||
|
||||
attr_reader :type, :io, :origin, :origins, :state, :pending, :options
|
||||
attr_reader :type, :io, :origin, :origins, :state, :pending, :options, :ssl_session
|
||||
|
||||
attr_writer :timers
|
||||
|
||||
@ -138,6 +138,12 @@ module HTTPX
|
||||
|
||||
def merge(connection)
|
||||
@origins |= connection.instance_variable_get(:@origins)
|
||||
if connection.ssl_session
|
||||
@ssl_session = connection.ssl_session
|
||||
@io.session_new_cb do |sess|
|
||||
@ssl_session = sess
|
||||
end if @io
|
||||
end
|
||||
connection.purge_pending do |req|
|
||||
send(req)
|
||||
end
|
||||
@ -594,14 +600,21 @@ module HTTPX
|
||||
end
|
||||
|
||||
def build_socket(addrs = nil)
|
||||
transport_type = case @type
|
||||
when "tcp" then TCP
|
||||
when "ssl" then SSL
|
||||
when "unix" then UNIX
|
||||
else
|
||||
raise Error, "unsupported transport (#{@type})"
|
||||
case @type
|
||||
when "tcp"
|
||||
TCP.new(@origin, addrs, @options)
|
||||
when "ssl"
|
||||
sock = SSL.new(@origin, addrs, @options)
|
||||
sock.ssl_session = @ssl_session
|
||||
sock.session_new_cb do |sess|
|
||||
@ssl_session = sess
|
||||
end
|
||||
sock
|
||||
when "unix"
|
||||
UNIX.new(@origin, addrs, @options)
|
||||
else
|
||||
raise Error, "unsupported transport (#{@type})"
|
||||
end
|
||||
transport_type.new(@origin, addrs, @options)
|
||||
end
|
||||
|
||||
def on_error(error)
|
||||
|
||||
@ -15,6 +15,8 @@ module HTTPX
|
||||
{}.freeze
|
||||
end
|
||||
|
||||
attr_writer :ssl_session
|
||||
|
||||
def initialize(_, _, options)
|
||||
super
|
||||
|
||||
@ -39,6 +41,15 @@ module HTTPX
|
||||
@verify_hostname = @ctx.verify_hostname
|
||||
end
|
||||
|
||||
if OpenSSL::SSL::SSLContext.method_defined?(:session_new_cb=)
|
||||
def session_new_cb(&pr)
|
||||
@ctx.session_new_cb = proc { |_, sess| pr.call(sess) }
|
||||
end
|
||||
else
|
||||
# session_new_cb not implemented under JRuby
|
||||
def session_new_cb; end
|
||||
end
|
||||
|
||||
def protocol
|
||||
@io.alpn_protocol || super
|
||||
rescue StandardError
|
||||
@ -81,6 +92,11 @@ module HTTPX
|
||||
else
|
||||
@io.hostname = @sni_hostname
|
||||
end
|
||||
if @ssl_session &&
|
||||
Process.clock_gettime(Process::CLOCK_REALTIME) < (@ssl_session.time.to_f + @ssl_session.timeout)
|
||||
puts "reusing session y'all: #{@ssl_session}"
|
||||
@io.session = @ssl_session
|
||||
end
|
||||
@io.sync_close = true
|
||||
end
|
||||
try_ssl_connect
|
||||
|
||||
@ -93,6 +93,10 @@ class HTTPSTest < Minitest::Test
|
||||
connection_count = http.pool.connection_count
|
||||
assert connection_count == 2, "expected to have 2 connections, instead have #{connection_count}"
|
||||
assert http.connection_exausted, "expected 1 connnection to have exhausted"
|
||||
|
||||
# ssl session ought to be reused
|
||||
conn = http.pool.connections.first
|
||||
assert conn.io.instance_variable_get(:@io).session_reused? unless RUBY_ENGINE == "jruby"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user