@@ -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'
@@ -1182,6 +1182,7 @@ def initialize(address, port = nil) # :nodoc:
11821182 @debug_output = options [ :debug_output ]
11831183 @response_body_encoding = options [ :response_body_encoding ]
11841184 @ignore_eof = options [ :ignore_eof ]
1185+ @tcpsocket_supports_open_timeout = nil
11851186
11861187 @proxy_from_env = false
11871188 @proxy_uri = nil
@@ -1324,6 +1325,9 @@ def response_body_encoding=(value)
13241325 # Sets the proxy password;
13251326 # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
13261327 attr_writer :proxy_pass
1328+
1329+ # Sets wheter the proxy uses SSL;
1330+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
13271331 attr_writer :proxy_use_ssl
13281332
13291333 # Returns the IP address for the connection.
@@ -1653,6 +1657,21 @@ def start # :yield: http
16531657 self
16541658 end
16551659
1660+ # Finishes the \HTTP session:
1661+ #
1662+ # http = Net::HTTP.new(hostname)
1663+ # http.start
1664+ # http.started? # => true
1665+ # http.finish # => nil
1666+ # http.started? # => false
1667+ #
1668+ # Raises IOError if not in a session.
1669+ def finish
1670+ raise IOError , 'HTTP session not yet started' unless started?
1671+ do_finish
1672+ end
1673+
1674+ # :stopdoc:
16561675 def do_start
16571676 connect
16581677 @started = true
@@ -1675,14 +1694,36 @@ def connect
16751694 end
16761695
16771696 debug "opening connection to #{ conn_addr } :#{ conn_port } ..."
1678- s = Timeout . timeout ( @open_timeout , Net ::OpenTimeout ) {
1679- begin
1680- TCPSocket . open ( conn_addr , conn_port , @local_host , @local_port )
1681- rescue => e
1682- raise e , "Failed to open TCP connection to " +
1683- "#{ conn_addr } :#{ conn_port } (#{ e . message } )"
1684- end
1685- }
1697+ begin
1698+ s =
1699+ case @tcpsocket_supports_open_timeout
1700+ when nil , true
1701+ begin
1702+ # Use built-in timeout in TCPSocket.open if available
1703+ sock = TCPSocket . open ( conn_addr , conn_port , @local_host , @local_port , open_timeout : @open_timeout )
1704+ @tcpsocket_supports_open_timeout = true
1705+ sock
1706+ rescue ArgumentError => e
1707+ raise if !( e . message . include? ( 'unknown keyword: :open_timeout' ) || e . message . include? ( 'wrong number of arguments (given 5, expected 2..4)' ) )
1708+ @tcpsocket_supports_open_timeout = false
1709+
1710+ # Fallback to Timeout.timeout if TCPSocket.open does not support open_timeout
1711+ Timeout . timeout ( @open_timeout , Net ::OpenTimeout ) {
1712+ TCPSocket . open ( conn_addr , conn_port , @local_host , @local_port )
1713+ }
1714+ end
1715+ when false
1716+ # The current Ruby is known to not support TCPSocket(open_timeout:).
1717+ # Directly fall back to Timeout.timeout to avoid performance penalty incured by rescue.
1718+ Timeout . timeout ( @open_timeout , Net ::OpenTimeout ) {
1719+ TCPSocket . open ( conn_addr , conn_port , @local_host , @local_port )
1720+ }
1721+ end
1722+ rescue => e
1723+ e = Net ::OpenTimeout . new ( e ) if e . is_a? ( Errno ::ETIMEDOUT ) # for compatibility with previous versions
1724+ raise e , "Failed to open TCP connection to " +
1725+ "#{ conn_addr } :#{ conn_port } (#{ e . message } )"
1726+ end
16861727 s . setsockopt ( Socket ::IPPROTO_TCP , Socket ::TCP_NODELAY , 1 )
16871728 debug "opened"
16881729 if use_ssl?
@@ -1779,20 +1820,6 @@ def on_connect
17791820 end
17801821 private :on_connect
17811822
1782- # Finishes the \HTTP session:
1783- #
1784- # http = Net::HTTP.new(hostname)
1785- # http.start
1786- # http.started? # => true
1787- # http.finish # => nil
1788- # http.started? # => false
1789- #
1790- # Raises IOError if not in a session.
1791- def finish
1792- raise IOError , 'HTTP session not yet started' unless started?
1793- do_finish
1794- end
1795-
17961823 def do_finish
17971824 @started = false
17981825 @socket . close if @socket
@@ -1842,6 +1869,8 @@ def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_use_ss
18421869 }
18431870 end
18441871
1872+ # :startdoc:
1873+
18451874 class << HTTP
18461875 # Returns true if self is a class which was created by HTTP::Proxy.
18471876 def proxy_class?
@@ -1936,6 +1965,7 @@ def proxy_pass
19361965 alias proxyport proxy_port #:nodoc: obsolete
19371966
19381967 private
1968+ # :stopdoc:
19391969
19401970 def unescape ( value )
19411971 require 'cgi/escape'
@@ -1964,6 +1994,7 @@ def edit_path(path)
19641994 path
19651995 end
19661996 end
1997+ # :startdoc:
19671998
19681999 #
19692000 # HTTP operations
@@ -2418,6 +2449,8 @@ def send_entity(path, data, initheader, dest, type, &block)
24182449 res
24192450 end
24202451
2452+ # :stopdoc:
2453+
24212454 IDEMPOTENT_METHODS_ = %w/ GET HEAD PUT DELETE OPTIONS TRACE / # :nodoc:
24222455
24232456 def transport_request ( req )
@@ -2575,7 +2608,7 @@ def debug(msg)
25752608 alias_method :D , :debug
25762609 end
25772610
2578- # for backward compatibility until Ruby 3.5
2611+ # for backward compatibility until Ruby 4.0
25792612 # https://bugs.ruby-lang.org/issues/20900
25802613 # https://github.com/bblimke/webmock/pull/1081
25812614 HTTPSession = HTTP
0 commit comments