Class: HTTP::Timeout::Null

Inherits:
Object
  • Object
show all
Defined in:
lib/http/timeout/null.rb,
sig/http.rbs

Overview

Base timeout handler with no timeout enforcement

Direct Known Subclasses

Global, PerOperation

Constant Summary collapse

NATIVE_CONNECT_TIMEOUT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Whether TCPSocket natively supports connect_timeout and Happy Eyeballs (RFC 8305). Available in Ruby 3.4+.

Returns:

  • (Boolean)
RUBY_VERSION >= "3.4"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(read_timeout: nil, write_timeout: nil, connect_timeout: nil, global_timeout: nil) ⇒ HTTP::Timeout::Null

Initializes the null timeout handler

Examples:

HTTP::Timeout::Null.new(read_timeout: 5)

Parameters:

  • read_timeout (Numeric, nil) (defaults to: nil)

    Read timeout in seconds

  • write_timeout (Numeric, nil) (defaults to: nil)

    Write timeout in seconds

  • connect_timeout (Numeric, nil) (defaults to: nil)

    Connect timeout in seconds

  • global_timeout (Numeric, nil) (defaults to: nil)

    Global timeout in seconds

  • read_timeout: (Numeric, nil) (defaults to: nil)
  • write_timeout: (Numeric, nil) (defaults to: nil)
  • connect_timeout: (Numeric, nil) (defaults to: nil)
  • global_timeout: (Numeric, nil) (defaults to: nil)


46
47
48
49
# File 'lib/http/timeout/null.rb', line 46

def initialize(read_timeout: nil, write_timeout: nil, connect_timeout: nil, global_timeout: nil)
  @options = { read_timeout: read_timeout, write_timeout: write_timeout,
               connect_timeout: connect_timeout, global_timeout: global_timeout }.compact
end

Instance Attribute Details

#optionsHash (readonly)

Timeout configuration options

Examples:

timeout.options # => {read_timeout: 5}

Returns:

  • (Hash)

    timeout options



24
25
26
# File 'lib/http/timeout/null.rb', line 24

def options
  @options
end

#socketObject (readonly)

The underlying socket

Examples:

timeout.socket

Returns:

  • (Object)

    the underlying socket



33
34
35
# File 'lib/http/timeout/null.rb', line 33

def socket
  @socket
end

Instance Method Details

#closevoid

This method returns an undefined value.

Closes the underlying socket

Examples:

timeout.close


85
86
87
# File 'lib/http/timeout/null.rb', line 85

def close
  @socket&.close
end

#closed?Boolean

Checks whether the socket is closed

Examples:

timeout.closed?

Returns:

  • (Boolean)


96
97
98
# File 'lib/http/timeout/null.rb', line 96

def closed?
  @socket&.closed?
end

#connect(socket_class, host, port, nodelay: false) ⇒ void

This method returns an undefined value.

Connects to a socket

Examples:

timeout.connect(TCPSocket, "example.com", 80)

Parameters:

  • socket_class (Class)
  • host (String)
  • port (Integer)
  • nodelay (Boolean) (defaults to: false)
  • nodelay: (Boolean) (defaults to: false)


62
63
64
65
# File 'lib/http/timeout/null.rb', line 62

def connect(socket_class, host, port, nodelay: false)
  @socket = open_socket(socket_class, host, port)
  @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
end

#connect_sslvoid

This method returns an undefined value.

Starts a SSL connection on a socket

Examples:

timeout.connect_ssl


74
75
76
# File 'lib/http/timeout/null.rb', line 74

def connect_ssl
  @socket.connect
end

#native_timeout?(socket_class) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Whether the socket class supports native connect_timeout

Parameters:

  • socket_class (Class)

    socket class to check

Returns:

  • (Boolean)


222
223
224
# File 'lib/http/timeout/null.rb', line 222

def native_timeout?(socket_class)
  NATIVE_CONNECT_TIMEOUT && socket_class.is_a?(Class) && socket_class <= TCPSocket
end

#open_socket(socket_class, host, port, connect_timeout: nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Opens a TCP socket, using native connect_timeout when available

On Ruby 3.4+ with TCPSocket, passes connect_timeout natively to enable proper Happy Eyeballs (RFC 8305) support. Falls back to Timeout.timeout on older Rubies or with custom socket classes.

Parameters:

  • socket_class (Class)

    socket class to create

  • host (String)

    remote hostname

  • port (Integer)

    remote port

  • connect_timeout (Numeric, nil) (defaults to: nil)

    timeout in seconds

  • connect_timeout: (Numeric, nil) (defaults to: nil)

Returns:

  • (Object)

    the connected socket



187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/http/timeout/null.rb', line 187

def open_socket(socket_class, host, port, connect_timeout: nil)
  return socket_class.open(host, port) unless connect_timeout

  if native_timeout?(socket_class)
    open_with_timeout(socket_class, host, port, connect_timeout)
  else
    ::Timeout.timeout(connect_timeout, ConnectTimeoutError) do
      open_with_timeout(socket_class, host, port, connect_timeout)
    end
  end
rescue IO::TimeoutError
  raise ConnectTimeoutError, "Connect timed out after #{connect_timeout} seconds"
end

#open_with_timeout(socket_class, host, port, connect_timeout) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Opens a socket, passing connect_timeout natively when supported

Parameters:

  • socket_class (Class)

    socket class to create

  • host (String)

    remote hostname

  • port (Integer)

    remote port

  • connect_timeout (Numeric)

    timeout in seconds

Returns:

  • (Object)

    the connected socket



209
210
211
212
213
214
215
# File 'lib/http/timeout/null.rb', line 209

def open_with_timeout(socket_class, host, port, connect_timeout)
  if native_timeout?(socket_class)
    socket_class.open(host, port, connect_timeout: connect_timeout)
  else
    socket_class.open(host, port)
  end
end

#read_timeoutNumeric?

Returns:

  • (Numeric, nil)


1511
# File 'sig/http.rbs', line 1511

def read_timeout: () -> Numeric?

#readpartial(size, buffer = nil) ⇒ String, :eof

Read from the socket

Examples:

timeout.readpartial(1024)

Parameters:

  • size (Integer)
  • buffer (String, nil) (defaults to: nil)

Returns:

  • (String, :eof)


132
133
134
135
136
# File 'lib/http/timeout/null.rb', line 132

def readpartial(size, buffer = nil)
  @socket.readpartial(size, buffer)
rescue EOFError
  :eof
end

#rescue_readable(timeout = read_timeout) { ... } ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Retries reading on wait readable

Parameters:

  • timeout (Numeric, nil) (defaults to: read_timeout)

Yields:

Yield Returns:

  • (Object)

Returns:

  • (Object)


157
158
159
160
161
162
# File 'lib/http/timeout/null.rb', line 157

def rescue_readable(timeout = read_timeout)
  yield
rescue IO::WaitReadable
  retry if @socket.to_io.wait_readable(timeout)
  raise TimeoutError, "Read timed out after #{timeout} seconds"
end

#rescue_writable(timeout = write_timeout) { ... } ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Retries writing on wait writable

Parameters:

  • timeout (Numeric, nil) (defaults to: write_timeout)

Yields:

Yield Returns:

  • (Object)

Returns:

  • (Object)


168
169
170
171
172
173
# File 'lib/http/timeout/null.rb', line 168

def rescue_writable(timeout = write_timeout)
  yield
rescue IO::WaitWritable
  retry if @socket.to_io.wait_writable(timeout)
  raise TimeoutError, "Write timed out after #{timeout} seconds"
end

#start_tls(host, ssl_socket_class, ssl_context) ⇒ void

This method returns an undefined value.

Configures the SSL connection and starts it

Examples:

timeout.start_tls("example.com", ssl_class, ssl_ctx)

Parameters:

  • host (String)
  • ssl_socket_class (Class)
  • ssl_context (OpenSSL::SSL::SSLContext)


110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/http/timeout/null.rb', line 110

def start_tls(host, ssl_socket_class, ssl_context)
  @socket = ssl_socket_class.new(socket, ssl_context)
  @socket.hostname = host if @socket.respond_to? :hostname=
  @socket.sync_close = true if @socket.respond_to? :sync_close=

  connect_ssl

  return unless ssl_context.verify_mode == OpenSSL::SSL::VERIFY_PEER
  return if ssl_context.respond_to?(:verify_hostname) && !ssl_context.verify_hostname

  @socket.post_connection_check(host)
end

#write(data) ⇒ Integer Also known as: <<

Write to the socket

Examples:

timeout.write("GET / HTTP/1.1")

Parameters:

  • data (String)

Returns:

  • (Integer)


146
147
148
# File 'lib/http/timeout/null.rb', line 146

def write(data)
  @socket.write(data)
end

#write_timeoutNumeric?

Returns:

  • (Numeric, nil)


1512
# File 'sig/http.rbs', line 1512

def write_timeout: () -> Numeric?