Skip to content

Commit ad76b37

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 edc99a5 commit ad76b37

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

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

0 commit comments

Comments
 (0)