@@ -724,7 +724,7 @@ class HTTPHeaderSyntaxError < StandardError; end
724724 class HTTP < Protocol
725725
726726 # :stopdoc:
727- VERSION = "0.7 .0"
727+ VERSION = "0.8 .0"
728728 HTTPVersion = '1.1'
729729 begin
730730 require 'zlib'
@@ -1179,6 +1179,7 @@ def initialize(address, port = nil) # :nodoc:
11791179 @debug_output = options [ :debug_output ]
11801180 @response_body_encoding = options [ :response_body_encoding ]
11811181 @ignore_eof = options [ :ignore_eof ]
1182+ @tcpsocket_supports_open_timeout = nil
11821183
11831184 @proxy_from_env = false
11841185 @proxy_uri = nil
@@ -1321,6 +1322,9 @@ def response_body_encoding=(value)
13211322 # Sets the proxy password;
13221323 # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
13231324 attr_writer :proxy_pass
1325+
1326+ # Sets wheter the proxy uses SSL;
1327+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
13241328 attr_writer :proxy_use_ssl
13251329
13261330 # Returns the IP address for the connection.
@@ -1632,6 +1636,21 @@ def start # :yield: http
16321636 self
16331637 end
16341638
1639+ # Finishes the \HTTP session:
1640+ #
1641+ # http = Net::HTTP.new(hostname)
1642+ # http.start
1643+ # http.started? # => true
1644+ # http.finish # => nil
1645+ # http.started? # => false
1646+ #
1647+ # Raises IOError if not in a session.
1648+ def finish
1649+ raise IOError , 'HTTP session not yet started' unless started?
1650+ do_finish
1651+ end
1652+
1653+ # :stopdoc:
16351654 def do_start
16361655 connect
16371656 @started = true
@@ -1654,14 +1673,36 @@ def connect
16541673 end
16551674
16561675 debug "opening connection to #{ conn_addr } :#{ conn_port } ..."
1657- s = Timeout . timeout ( @open_timeout , Net ::OpenTimeout ) {
1658- begin
1659- TCPSocket . open ( conn_addr , conn_port , @local_host , @local_port )
1660- rescue => e
1661- raise e , "Failed to open TCP connection to " +
1662- "#{ conn_addr } :#{ conn_port } (#{ e . message } )"
1663- end
1664- }
1676+ begin
1677+ s =
1678+ case @tcpsocket_supports_open_timeout
1679+ when nil , true
1680+ begin
1681+ # Use built-in timeout in TCPSocket.open if available
1682+ sock = TCPSocket . open ( conn_addr , conn_port , @local_host , @local_port , open_timeout : @open_timeout )
1683+ @tcpsocket_supports_open_timeout = true
1684+ sock
1685+ rescue ArgumentError => e
1686+ raise if !( e . message . include? ( 'unknown keyword: :open_timeout' ) || e . message . include? ( 'wrong number of arguments (given 5, expected 2..4)' ) )
1687+ @tcpsocket_supports_open_timeout = false
1688+
1689+ # Fallback to Timeout.timeout if TCPSocket.open does not support open_timeout
1690+ Timeout . timeout ( @open_timeout , Net ::OpenTimeout ) {
1691+ TCPSocket . open ( conn_addr , conn_port , @local_host , @local_port )
1692+ }
1693+ end
1694+ when false
1695+ # The current Ruby is known to not support TCPSocket(open_timeout:).
1696+ # Directly fall back to Timeout.timeout to avoid performance penalty incured by rescue.
1697+ Timeout . timeout ( @open_timeout , Net ::OpenTimeout ) {
1698+ TCPSocket . open ( conn_addr , conn_port , @local_host , @local_port )
1699+ }
1700+ end
1701+ rescue => e
1702+ e = Net ::OpenTimeout . new ( e ) if e . is_a? ( Errno ::ETIMEDOUT ) # for compatibility with previous versions
1703+ raise e , "Failed to open TCP connection to " +
1704+ "#{ conn_addr } :#{ conn_port } (#{ e . message } )"
1705+ end
16651706 s . setsockopt ( Socket ::IPPROTO_TCP , Socket ::TCP_NODELAY , 1 )
16661707 debug "opened"
16671708 if use_ssl?
@@ -1758,20 +1799,6 @@ def on_connect
17581799 end
17591800 private :on_connect
17601801
1761- # Finishes the \HTTP session:
1762- #
1763- # http = Net::HTTP.new(hostname)
1764- # http.start
1765- # http.started? # => true
1766- # http.finish # => nil
1767- # http.started? # => false
1768- #
1769- # Raises IOError if not in a session.
1770- def finish
1771- raise IOError , 'HTTP session not yet started' unless started?
1772- do_finish
1773- end
1774-
17751802 def do_finish
17761803 @started = false
17771804 @socket . close if @socket
@@ -1821,6 +1848,8 @@ def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_use_ss
18211848 }
18221849 end
18231850
1851+ # :startdoc:
1852+
18241853 class << HTTP
18251854 # Returns true if self is a class which was created by HTTP::Proxy.
18261855 def proxy_class?
@@ -1915,6 +1944,7 @@ def proxy_pass
19151944 alias proxyport proxy_port #:nodoc: obsolete
19161945
19171946 private
1947+ # :stopdoc:
19181948
19191949 def unescape ( value )
19201950 require 'cgi/escape'
@@ -1943,6 +1973,7 @@ def edit_path(path)
19431973 path
19441974 end
19451975 end
1976+ # :startdoc:
19461977
19471978 #
19481979 # HTTP operations
@@ -2397,6 +2428,8 @@ def send_entity(path, data, initheader, dest, type, &block)
23972428 res
23982429 end
23992430
2431+ # :stopdoc:
2432+
24002433 IDEMPOTENT_METHODS_ = %w/ GET HEAD PUT DELETE OPTIONS TRACE / # :nodoc:
24012434
24022435 def transport_request ( req )
@@ -2554,7 +2587,7 @@ def debug(msg)
25542587 alias_method :D , :debug
25552588 end
25562589
2557- # for backward compatibility until Ruby 3.5
2590+ # for backward compatibility until Ruby 4.0
25582591 # https://bugs.ruby-lang.org/issues/20900
25592592 # https://github.com/bblimke/webmock/pull/1081
25602593 HTTPSession = HTTP
0 commit comments