Skip to content

Commit 0061a7c

Browse files
committed
Refactor Net::HTTP#connect
The method was getting large, and in preparation for #141, I thought it would be easier to break up the method into several other methods.
1 parent 705e7c0 commit 0061a7c

File tree

1 file changed

+83
-67
lines changed

1 file changed

+83
-67
lines changed

lib/net/http.rb

Lines changed: 83 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,73 +1610,10 @@ def connect
16101610
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
16111611
debug "opened"
16121612
if use_ssl?
1613-
if proxy?
1614-
plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
1615-
write_timeout: @write_timeout,
1616-
continue_timeout: @continue_timeout,
1617-
debug_output: @debug_output)
1618-
buf = "CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n"
1619-
buf << "Host: #{@address}:#{@port}\r\n"
1620-
if proxy_user
1621-
credential = ["#{proxy_user}:#{proxy_pass}"].pack('m0')
1622-
buf << "Proxy-Authorization: Basic #{credential}\r\n"
1623-
end
1624-
buf << "\r\n"
1625-
plain_sock.write(buf)
1626-
HTTPResponse.read_new(plain_sock).value
1627-
# assuming nothing left in buffers after successful CONNECT response
1628-
end
1629-
1630-
ssl_parameters = Hash.new
1631-
iv_list = instance_variables
1632-
SSL_IVNAMES.each_with_index do |ivname, i|
1633-
if iv_list.include?(ivname)
1634-
value = instance_variable_get(ivname)
1635-
unless value.nil?
1636-
ssl_parameters[SSL_ATTRIBUTES[i]] = value
1637-
end
1638-
end
1639-
end
1640-
@ssl_context.set_params(ssl_parameters)
1641-
unless @ssl_context.session_cache_mode.nil? # a dummy method on JRuby
1642-
@ssl_context.session_cache_mode =
1643-
OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
1644-
OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
1645-
end
1646-
if @ssl_context.respond_to?(:session_new_cb) # not implemented under JRuby
1647-
@ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
1648-
end
1649-
1650-
# Still do the post_connection_check below even if connecting
1651-
# to IP address
1652-
verify_hostname = @ssl_context.verify_hostname
1653-
1654-
# Server Name Indication (SNI) RFC 3546/6066
1655-
case @address
1656-
when Resolv::IPv4::Regex, Resolv::IPv6::Regex
1657-
# don't set SNI, as IP addresses in SNI is not valid
1658-
# per RFC 6066, section 3.
1659-
1660-
# Avoid openssl warning
1661-
@ssl_context.verify_hostname = false
1662-
else
1663-
ssl_host_address = @address
1664-
end
1665-
1666-
debug "starting SSL for #{conn_addr}:#{conn_port}..."
1667-
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
1668-
s.sync_close = true
1669-
s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address
1670-
1671-
if @ssl_session and
1672-
Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
1673-
s.session = @ssl_session
1674-
end
1675-
ssl_socket_connect(s, @open_timeout)
1676-
if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
1677-
s.post_connection_check(@address)
1678-
end
1679-
debug "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
1613+
proxy_connect(s, conn_address) if proxy?
1614+
setup_ssl_context
1615+
s = setup_ssl_socket(s, conn_addr, conn_port)
1616+
ssl_connect(s)
16801617
end
16811618
@socket = BufferedIO.new(s, read_timeout: @read_timeout,
16821619
write_timeout: @write_timeout,
@@ -1693,6 +1630,85 @@ def connect
16931630
end
16941631
private :connect
16951632

1633+
def proxy_connect(s, conn_address)
1634+
plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
1635+
write_timeout: @write_timeout,
1636+
continue_timeout: @continue_timeout,
1637+
debug_output: @debug_output)
1638+
buf = "CONNECT #{conn_address}:#{@port} HTTP/#{HTTPVersion}\r\n"
1639+
buf << "Host: #{@address}:#{@port}\r\n"
1640+
if proxy_user
1641+
credential = ["#{proxy_user}:#{proxy_pass}"].pack('m0')
1642+
buf << "Proxy-Authorization: Basic #{credential}\r\n"
1643+
end
1644+
buf << "\r\n"
1645+
plain_sock.write(buf)
1646+
HTTPResponse.read_new(plain_sock).value
1647+
# assuming nothing left in buffers after successful CONNECT response
1648+
end
1649+
private :proxy_connect
1650+
1651+
def setup_ssl_context
1652+
ssl_parameters = Hash.new
1653+
iv_list = instance_variables
1654+
SSL_IVNAMES.each_with_index do |ivname, i|
1655+
if iv_list.include?(ivname)
1656+
value = instance_variable_get(ivname)
1657+
unless value.nil?
1658+
ssl_parameters[SSL_ATTRIBUTES[i]] = value
1659+
end
1660+
end
1661+
end
1662+
@ssl_context.set_params(ssl_parameters)
1663+
unless @ssl_context.session_cache_mode.nil? # a dummy method on JRuby
1664+
@ssl_context.session_cache_mode =
1665+
OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
1666+
OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
1667+
end
1668+
if @ssl_context.respond_to?(:session_new_cb) # not implemented under JRuby
1669+
@ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
1670+
end
1671+
end
1672+
private :setup_ssl_context
1673+
1674+
def setup_ssl_socket(s, conn_addr, conn_port)
1675+
# Still do the post_connection_check below even if connecting
1676+
# to IP address
1677+
verify_hostname = @ssl_context.verify_hostname
1678+
1679+
# Server Name Indication (SNI) RFC 3546/6066
1680+
case @address
1681+
when Resolv::IPv4::Regex, Resolv::IPv6::Regex
1682+
# don't set SNI, as IP addresses in SNI is not valid
1683+
# per RFC 6066, section 3.
1684+
1685+
# Avoid openssl warning
1686+
@ssl_context.verify_hostname = false
1687+
else
1688+
ssl_host_address = @address
1689+
end
1690+
1691+
debug "starting SSL for #{conn_addr}:#{conn_port}..."
1692+
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
1693+
s.sync_close = true
1694+
s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address
1695+
s
1696+
end
1697+
private :setup_ssl_socket
1698+
1699+
def ssl_connect(s)
1700+
if @ssl_session and
1701+
Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
1702+
s.session = @ssl_session
1703+
end
1704+
ssl_socket_connect(s, @open_timeout)
1705+
if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
1706+
s.post_connection_check(@address)
1707+
end
1708+
debug "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
1709+
end
1710+
private :ssl_connect
1711+
16961712
def on_connect
16971713
end
16981714
private :on_connect

0 commit comments

Comments
 (0)