httpx 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/httpx/request.rb CHANGED
@@ -4,20 +4,50 @@ require "delegate"
4
4
  require "forwardable"
5
5
 
6
6
  module HTTPX
7
+ # Defines how an HTTP request is handled internally, both in terms of making attributes accessible,
8
+ # as well as maintaining the state machine which manages streaming the request onto the wire.
7
9
  class Request
8
10
  extend Forwardable
9
11
  include Callbacks
10
12
  using URIExtensions
11
13
 
14
+ # default value used for "user-agent" header, when not overridden.
12
15
  USER_AGENT = "httpx.rb/#{VERSION}"
13
16
 
14
- attr_reader :verb, :uri, :headers, :body, :state, :options, :response
17
+ # the upcased string HTTP verb for this request.
18
+ attr_reader :verb
15
19
 
16
- # Exception raised during enumerable body writes
20
+ # the absolute URI object for this request.
21
+ attr_reader :uri
22
+
23
+ # an HTTPX::Headers object containing the request HTTP headers.
24
+ attr_reader :headers
25
+
26
+ # an HTTPX::Request::Body object containing the request body payload (or +nil+, whenn there is none).
27
+ attr_reader :body
28
+
29
+ # a symbol describing which frame is currently being flushed.
30
+ attr_reader :state
31
+
32
+ # an HTTPX::Options object containing request options.
33
+ attr_reader :options
34
+
35
+ # the corresponding HTTPX::Response object, when there is one.
36
+ attr_reader :response
37
+
38
+ # Exception raised during enumerable body writes.
17
39
  attr_reader :drain_error
18
40
 
41
+ # The IP address from the peer server.
42
+ attr_accessor :peer_address
43
+
44
+ attr_writer :persistent
45
+
46
+ # will be +true+ when request body has been completely flushed.
19
47
  def_delegator :@body, :empty?
20
48
 
49
+ # initializes the instance with the given +verb+, an absolute or relative +uri+, and the
50
+ # request options.
21
51
  def initialize(verb, uri, options = {})
22
52
  @verb = verb.to_s.upcase
23
53
  @options = Options.new(options)
@@ -37,20 +67,30 @@ module HTTPX
37
67
 
38
68
  @body = @options.request_body_class.new(@headers, @options)
39
69
  @state = :idle
70
+ @response = nil
71
+ @peer_address = nil
72
+ @persistent = @options.persistent
40
73
  end
41
74
 
75
+ # the read timeout defied for this requet.
42
76
  def read_timeout
43
77
  @options.timeout[:read_timeout]
44
78
  end
45
79
 
80
+ # the write timeout defied for this requet.
46
81
  def write_timeout
47
82
  @options.timeout[:write_timeout]
48
83
  end
49
84
 
85
+ # the request timeout defied for this requet.
50
86
  def request_timeout
51
87
  @options.timeout[:request_timeout]
52
88
  end
53
89
 
90
+ def persistent?
91
+ @persistent
92
+ end
93
+
54
94
  def trailers?
55
95
  defined?(@trailers)
56
96
  end
@@ -59,6 +99,7 @@ module HTTPX
59
99
  @trailers ||= @options.headers_class.new
60
100
  end
61
101
 
102
+ # returns +:r+ or +:w+, depending on whether the request is waiting for a response or flushing.
62
103
  def interests
63
104
  return :r if @state == :done || @state == :expect
64
105
 
@@ -69,10 +110,12 @@ module HTTPX
69
110
  @headers = @headers.merge(h)
70
111
  end
71
112
 
113
+ # the URI scheme of the request +uri+.
72
114
  def scheme
73
115
  @uri.scheme
74
116
  end
75
117
 
118
+ # sets the +response+ on this request.
76
119
  def response=(response)
77
120
  return unless response
78
121
 
@@ -85,6 +128,7 @@ module HTTPX
85
128
  emit(:response_started, response)
86
129
  end
87
130
 
131
+ # returnns the URI path of the request +uri+.
88
132
  def path
89
133
  path = uri.path.dup
90
134
  path = +"" if path.nil?
@@ -93,16 +137,28 @@ module HTTPX
93
137
  path
94
138
  end
95
139
 
96
- # https://bugs.ruby-lang.org/issues/15278
140
+ # returs the URI authority of the request.
141
+ #
142
+ # session.build_request("GET", "https://google.com/query").authority #=> "google.com"
143
+ # session.build_request("GET", "http://internal:3182/a").authority #=> "internal:3182"
97
144
  def authority
98
145
  @uri.authority
99
146
  end
100
147
 
101
- # https://bugs.ruby-lang.org/issues/15278
148
+ # returs the URI origin of the request.
149
+ #
150
+ # session.build_request("GET", "https://google.com/query").authority #=> "https://google.com"
151
+ # session.build_request("GET", "http://internal:3182/a").authority #=> "http://internal:3182"
102
152
  def origin
103
153
  @uri.origin
104
154
  end
105
155
 
156
+ # returs the URI query string of the request (when available).
157
+ #
158
+ # session.build_request("GET", "https://search.com").query #=> ""
159
+ # session.build_request("GET", "https://search.com?q=a").query #=> "q=a"
160
+ # session.build_request("GET", "https://search.com", params: { q: "a"}).query #=> "q=a"
161
+ # session.build_request("GET", "https://search.com?q=a", params: { foo: "bar"}).query #=> "q=a&foo&bar"
106
162
  def query
107
163
  return @query if defined?(@query)
108
164
 
@@ -114,6 +170,7 @@ module HTTPX
114
170
  @query = query.join("&")
115
171
  end
116
172
 
173
+ # consumes and returns the next available chunk of request body that can be sent
117
174
  def drain_body
118
175
  return nil if @body.nil?
119
176
 
@@ -139,6 +196,7 @@ module HTTPX
139
196
  end
140
197
  # :nocov:
141
198
 
199
+ # moves on to the +nextstate+ of the request state machine (when all preconditions are met)
142
200
  def transition(nextstate)
143
201
  case nextstate
144
202
  when :idle
@@ -173,6 +231,7 @@ module HTTPX
173
231
  nil
174
232
  end
175
233
 
234
+ # whether the request supports the 100-continue handshake and already processed the 100 response.
176
235
  def expects?
177
236
  @headers["expect"] == "100-continue" && @informational_status == 100 && !@response
178
237
  end
@@ -30,7 +30,7 @@ module HTTPX
30
30
  nameserver = nameserver[family] if nameserver.is_a?(Hash)
31
31
  Array(nameserver)
32
32
  end
33
- @ndots = @resolver_options[:ndots]
33
+ @ndots = @resolver_options.fetch(:ndots, 1)
34
34
  @search = Array(@resolver_options[:search]).map { |srch| srch.scan(/[^.]+/) }
35
35
  @_timeouts = Array(@resolver_options[:timeouts])
36
36
  @timeouts = Hash.new { |timeouts, host| timeouts[host] = @_timeouts.dup }
@@ -103,7 +103,7 @@ module HTTPX
103
103
  @timeouts.values_at(*hosts).reject(&:empty?).map(&:first).min
104
104
  end
105
105
 
106
- def raise_timeout_error(interval)
106
+ def handle_socket_timeout(interval)
107
107
  do_retry(interval)
108
108
  end
109
109
 
@@ -92,7 +92,7 @@ module HTTPX
92
92
  resolve
93
93
  end
94
94
 
95
- def raise_timeout_error(interval)
95
+ def handle_socket_timeout(interval)
96
96
  error = HTTPX::ResolveTimeoutError.new(interval, "timed out while waiting on select")
97
97
  error.set_backtrace(caller)
98
98
  on_error(error)
@@ -1,19 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
+ # Implementation of the HTTP Response body as a buffer which implements the IO writer protocol
5
+ # (for buffering the response payload), the IO reader protocol (for consuming the response payload),
6
+ # and can be iterated over (via #each, which yields the payload in chunks).
4
7
  class Response::Body
5
- attr_reader :encoding, :encodings
8
+ # the payload encoding (i.e. "utf-8", "ASCII-8BIT")
9
+ attr_reader :encoding
6
10
 
11
+ # Array of encodings contained in the response "content-encoding" header.
12
+ attr_reader :encodings
13
+
14
+ # initialized with the corresponding HTTPX::Response +response+ and HTTPX::Options +options+.
7
15
  def initialize(response, options)
8
16
  @response = response
9
17
  @headers = response.headers
10
18
  @options = options
11
- @threshold_size = options.body_threshold_size
12
19
  @window_size = options.window_size
13
20
  @encoding = response.content_type.charset || Encoding::BINARY
14
21
  @encodings = []
15
22
  @length = 0
16
23
  @buffer = nil
24
+ @reader = nil
17
25
  @state = :idle
18
26
  initialize_inflaters
19
27
  end
@@ -28,6 +36,8 @@ module HTTPX
28
36
  @state == :closed
29
37
  end
30
38
 
39
+ # write the response payload +chunk+ into the buffer. Inflates the chunk when required
40
+ # and supported.
31
41
  def write(chunk)
32
42
  return if @state == :closed
33
43
 
@@ -44,6 +54,7 @@ module HTTPX
44
54
  size
45
55
  end
46
56
 
57
+ # reads a chunk from the payload (implementation of the IO reader protocol).
47
58
  def read(*args)
48
59
  return unless @buffer
49
60
 
@@ -55,10 +66,13 @@ module HTTPX
55
66
  @reader.read(*args)
56
67
  end
57
68
 
69
+ # size of the decoded response payload. May differ from "content-length" header if
70
+ # response was encoded over-the-wire.
58
71
  def bytesize
59
72
  @length
60
73
  end
61
74
 
75
+ # yields the payload in chunks.
62
76
  def each
63
77
  return enum_for(__method__) unless block_given?
64
78
 
@@ -74,12 +88,14 @@ module HTTPX
74
88
  end
75
89
  end
76
90
 
91
+ # returns the declared filename in the "contennt-disposition" header, when present.
77
92
  def filename
78
93
  return unless @headers.key?("content-disposition")
79
94
 
80
95
  Utils.get_filename(@headers["content-disposition"])
81
96
  end
82
97
 
98
+ # returns the full response payload as a string.
83
99
  def to_s
84
100
  return "".b unless @buffer
85
101
 
@@ -88,10 +104,16 @@ module HTTPX
88
104
 
89
105
  alias_method :to_str, :to_s
90
106
 
107
+ # whether the payload is empty.
91
108
  def empty?
92
109
  @length.zero?
93
110
  end
94
111
 
112
+ # copies the payload to +dest+.
113
+ #
114
+ # body.copy_to("path/to/file")
115
+ # body.copy_to(Pathname.new("path/to/file"))
116
+ # body.copy_to(File.new("path/to/file"))
95
117
  def copy_to(dest)
96
118
  return unless @buffer
97
119
 
@@ -132,6 +154,7 @@ module HTTPX
132
154
  end
133
155
  # :nocov:
134
156
 
157
+ # rewinds the response payload buffer.
135
158
  def rewind
136
159
  return unless @buffer
137
160
 
@@ -144,6 +167,8 @@ module HTTPX
144
167
  private
145
168
 
146
169
  def initialize_inflaters
170
+ @inflaters = nil
171
+
147
172
  return unless @headers.key?("content-encoding")
148
173
 
149
174
  return unless @options.decompress_response_body
@@ -168,7 +193,7 @@ module HTTPX
168
193
  return unless @state == :idle
169
194
 
170
195
  @buffer = Response::Buffer.new(
171
- threshold_size: @threshold_size,
196
+ threshold_size: @options.body_threshold_size,
172
197
  bytesize: @length,
173
198
  encoding: @encoding
174
199
  )
@@ -179,7 +204,7 @@ module HTTPX
179
204
  @state = nextstate
180
205
  end
181
206
 
182
- def _with_same_buffer_pos
207
+ def _with_same_buffer_pos # :nodoc:
183
208
  return yield unless @buffer && @buffer.respond_to?(:pos)
184
209
 
185
210
  # @type ivar @buffer: StringIO | Tempfile
@@ -193,7 +218,7 @@ module HTTPX
193
218
  end
194
219
 
195
220
  class << self
196
- def initialize_inflater_by_encoding(encoding, response, **kwargs)
221
+ def initialize_inflater_by_encoding(encoding, response, **kwargs) # :nodoc:
197
222
  case encoding
198
223
  when "gzip"
199
224
  Transcoder::GZIP.decode(response, **kwargs)
@@ -5,12 +5,15 @@ require "stringio"
5
5
  require "tempfile"
6
6
 
7
7
  module HTTPX
8
+ # wraps and delegates to an internal buffer, which can be a StringIO or a Tempfile.
8
9
  class Response::Buffer < SimpleDelegator
10
+ # initializes buffer with the +threshold_size+ over which the payload gets buffer to a tempfile,
11
+ # the initial +bytesize+, and the +encoding+.
9
12
  def initialize(threshold_size:, bytesize: 0, encoding: Encoding::BINARY)
10
13
  @threshold_size = threshold_size
11
14
  @bytesize = bytesize
12
15
  @encoding = encoding
13
- try_upgrade_buffer
16
+ @buffer = StringIO.new("".b)
14
17
  super(@buffer)
15
18
  end
16
19
 
@@ -20,16 +23,19 @@ module HTTPX
20
23
  @buffer = other.instance_variable_get(:@buffer).dup
21
24
  end
22
25
 
26
+ # size in bytes of the buffered content.
23
27
  def size
24
28
  @bytesize
25
29
  end
26
30
 
31
+ # writes the +chunk+ into the buffer.
27
32
  def write(chunk)
28
33
  @bytesize += chunk.bytesize
29
34
  try_upgrade_buffer
30
35
  @buffer.write(chunk)
31
36
  end
32
37
 
38
+ # returns the buffered content as a string.
33
39
  def to_s
34
40
  case @buffer
35
41
  when StringIO
@@ -49,6 +55,7 @@ module HTTPX
49
55
  end
50
56
  end
51
57
 
58
+ # closes the buffer.
52
59
  def close
53
60
  @buffer.close
54
61
  @buffer.unlink if @buffer.respond_to?(:unlink)
@@ -56,28 +63,27 @@ module HTTPX
56
63
 
57
64
  private
58
65
 
66
+ # initializes the buffer into a StringIO, or turns it into a Tempfile when the threshold
67
+ # has been reached.
59
68
  def try_upgrade_buffer
60
- if !@buffer.is_a?(Tempfile) && @bytesize > @threshold_size
61
- aux = @buffer
62
-
63
- @buffer = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR)
69
+ return unless @bytesize > @threshold_size
64
70
 
65
- if aux
66
- aux.rewind
67
- ::IO.copy_stream(aux, @buffer)
68
- aux.close
69
- end
71
+ return if @buffer.is_a?(Tempfile)
70
72
 
71
- else
72
- return if @buffer
73
+ aux = @buffer
73
74
 
74
- @buffer = StringIO.new("".b)
75
+ @buffer = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR)
75
76
 
77
+ if aux
78
+ aux.rewind
79
+ ::IO.copy_stream(aux, @buffer)
80
+ aux.close
76
81
  end
82
+
77
83
  __setobj__(@buffer)
78
84
  end
79
85
 
80
- def _with_same_buffer_pos
86
+ def _with_same_buffer_pos # :nodoc:
81
87
  current_pos = @buffer.pos
82
88
  @buffer.rewind
83
89
  begin
@@ -7,24 +7,48 @@ require "fileutils"
7
7
  require "forwardable"
8
8
 
9
9
  module HTTPX
10
+ # Defines a HTTP response is handled internally, with a few properties exposed as attributes,
11
+ # implements (indirectly, via the +body+) the IO write protocol to internally buffer payloads,
12
+ # implements the IO reader protocol in order for users to buffer/stream it, acts as an enumerable
13
+ # (of payload chunks).
10
14
  class Response
11
15
  extend Forwardable
12
16
  include Callbacks
13
17
 
14
- attr_reader :status, :headers, :body, :version
18
+ # the HTTP response status code
19
+ attr_reader :status
15
20
 
21
+ # an HTTPX::Headers object containing the response HTTP headers.
22
+ attr_reader :headers
23
+
24
+ # a HTTPX::Response::Body object wrapping the response body.
25
+ attr_reader :body
26
+
27
+ # The HTTP protocol version used to fetch the response.
28
+ attr_reader :version
29
+
30
+ # returns the response body buffered in a string.
16
31
  def_delegator :@body, :to_s
17
32
 
18
33
  def_delegator :@body, :to_str
19
34
 
35
+ # implements the IO reader +#read+ interface.
20
36
  def_delegator :@body, :read
21
37
 
38
+ # copies the response body to a different location.
22
39
  def_delegator :@body, :copy_to
23
40
 
41
+ # closes the body.
24
42
  def_delegator :@body, :close
25
43
 
44
+ # the corresponding request uri.
26
45
  def_delegator :@request, :uri
27
46
 
47
+ # the IP address of the peer server.
48
+ def_delegator :@request, :peer_address
49
+
50
+ # inits the instance with the corresponding +request+ to this response, an the
51
+ # response HTTP +status+, +version+ and HTTPX::Headers instance of +headers+.
28
52
  def initialize(request, status, version, headers)
29
53
  @request = request
30
54
  @options = request.options
@@ -33,32 +57,49 @@ module HTTPX
33
57
  @headers = @options.headers_class.new(headers)
34
58
  @body = @options.response_body_class.new(self, @options)
35
59
  @finished = complete?
60
+ @content_type = nil
36
61
  end
37
62
 
63
+ # merges headers defined in +h+ into the response headers.
38
64
  def merge_headers(h)
39
65
  @headers = @headers.merge(h)
40
66
  end
41
67
 
68
+ # writes +data+ chunk into the response body.
42
69
  def <<(data)
43
70
  @body.write(data)
44
71
  end
45
72
 
73
+ # returns the response mime type, as per what's declared in the content-type header.
74
+ #
75
+ # response.content_type #=> "text/plain"
46
76
  def content_type
47
77
  @content_type ||= ContentType.new(@headers["content-type"])
48
78
  end
49
79
 
80
+ # returns whether the response has been fully fetched.
50
81
  def finished?
51
82
  @finished
52
83
  end
53
84
 
85
+ # marks the response as finished, freezes the headers.
54
86
  def finish!
55
87
  @finished = true
56
88
  @headers.freeze
57
89
  end
58
90
 
91
+ # returns whether the response contains body payload.
59
92
  def bodyless?
60
93
  @request.verb == "HEAD" ||
61
- no_data?
94
+ @status < 200 || # informational response
95
+ @status == 204 ||
96
+ @status == 205 ||
97
+ @status == 304 || begin
98
+ content_length = @headers["content-length"]
99
+ return false if content_length.nil?
100
+
101
+ content_length == "0"
102
+ end
62
103
  end
63
104
 
64
105
  def complete?
@@ -75,32 +116,53 @@ module HTTPX
75
116
  end
76
117
  # :nocov:
77
118
 
119
+ # returns an instance of HTTPX::HTTPError if the response has a 4xx or 5xx
120
+ # status code, or nothing.
121
+ #
122
+ # ok_response.error #=> nil
123
+ # not_found_response.error #=> HTTPX::HTTPError instance, status 404
78
124
  def error
79
125
  return if @status < 400
80
126
 
81
127
  HTTPError.new(self)
82
128
  end
83
129
 
130
+ # it raises the exception returned by +error+, or itself otherwise.
131
+ #
132
+ # ok_response.raise_for_status #=> ok_response
133
+ # not_found_response.raise_for_status #=> raises HTTPX::HTTPError exception
84
134
  def raise_for_status
85
135
  return self unless (err = error)
86
136
 
87
137
  raise err
88
138
  end
89
139
 
140
+ # decodes the response payload into a ruby object **if** the payload is valid json.
141
+ #
142
+ # response.json #≈> { "foo" => "bar" } for "{\"foo\":\"bar\"}" payload
143
+ # response.json(symbolize_names: true) #≈> { foo: "bar" } for "{\"foo\":\"bar\"}" payload
90
144
  def json(*args)
91
145
  decode(Transcoder::JSON, *args)
92
146
  end
93
147
 
148
+ # decodes the response payload into a ruby object **if** the payload is valid
149
+ # "application/x-www-urlencoded" or "multipart/form-data".
94
150
  def form
95
151
  decode(Transcoder::Form)
96
152
  end
97
153
 
154
+ # decodes the response payload into a Nokogiri::XML::Node object **if** the payload is valid
155
+ # "application/xml" (requires the "nokogiri" gem).
98
156
  def xml
99
157
  decode(Transcoder::Xml)
100
158
  end
101
159
 
102
160
  private
103
161
 
162
+ # decodes the response payload using the given +transcoder+, which implements the decoding logic.
163
+ #
164
+ # +transcoder+ must implement the internal transcoder API, i.e. respond to <tt>decode(HTTPX::Response response)</tt>,
165
+ # which returns a decoder which responds to <tt>call(HTTPX::Response response, **kwargs)</tt>
104
166
  def decode(transcoder, *args)
105
167
  # TODO: check if content-type is a valid format, i.e. "application/json" for json parsing
106
168
 
@@ -112,20 +174,9 @@ module HTTPX
112
174
 
113
175
  decoder.call(self, *args)
114
176
  end
115
-
116
- def no_data?
117
- @status < 200 || # informational response
118
- @status == 204 ||
119
- @status == 205 ||
120
- @status == 304 || begin
121
- content_length = @headers["content-length"]
122
- return false if content_length.nil?
123
-
124
- content_length == "0"
125
- end
126
- end
127
177
  end
128
178
 
179
+ # Helper class which decodes the HTTP "content-type" header.
129
180
  class ContentType
130
181
  MIME_TYPE_RE = %r{^([^/]+/[^;]+)(?:$|;)}.freeze
131
182
  CHARSET_RE = /;\s*charset=([^;]+)/i.freeze
@@ -134,6 +185,9 @@ module HTTPX
134
185
  @header_value = header_value
135
186
  end
136
187
 
188
+ # returns the mime type declared in the header.
189
+ #
190
+ # ContentType.new("application/json; charset=utf-8").mime_type #=> "application/json"
137
191
  def mime_type
138
192
  return @mime_type if defined?(@mime_type)
139
193
 
@@ -141,6 +195,10 @@ module HTTPX
141
195
  m && @mime_type = m.strip.downcase
142
196
  end
143
197
 
198
+ # returns the charset declared in the header.
199
+ #
200
+ # ContentType.new("application/json; charset=utf-8").charset #=> "utf-8"
201
+ # ContentType.new("text/plain").charset #=> nil
144
202
  def charset
145
203
  return @charset if defined?(@charset)
146
204
 
@@ -149,14 +207,31 @@ module HTTPX
149
207
  end
150
208
  end
151
209
 
210
+ # Wraps an error which has happened while processing an HTTP Request. It has partial
211
+ # public API parity with HTTPX::Response, so users should rely on it to infer whether
212
+ # the returned response is one or the other.
213
+ #
214
+ # response = HTTPX.get("https://some-domain/path") #=> response is HTTPX::Response or HTTPX::ErrorResponse
215
+ # response.raise_for_status #=> raises if it wraps an error
152
216
  class ErrorResponse
153
217
  include Loggable
154
218
  extend Forwardable
155
219
 
156
- attr_reader :request, :response, :error
220
+ # the corresponding HTTPX::Request instance.
221
+ attr_reader :request
157
222
 
223
+ # the HTTPX::Response instance, when there is one (i.e. error happens fetching the response).
224
+ attr_reader :response
225
+
226
+ # the wrapped exception.
227
+ attr_reader :error
228
+
229
+ # the request uri
158
230
  def_delegator :@request, :uri
159
231
 
232
+ # the IP address of the peer server.
233
+ def_delegator :@request, :peer_address
234
+
160
235
  def initialize(request, error, options)
161
236
  @request = request
162
237
  @response = request.response if request.response.is_a?(Response)
@@ -165,18 +240,22 @@ module HTTPX
165
240
  log_exception(@error)
166
241
  end
167
242
 
243
+ # returns the exception full message.
168
244
  def to_s
169
245
  @error.full_message(highlight: false)
170
246
  end
171
247
 
248
+ # closes the error resources.
172
249
  def close
173
- @response.close if @response.respond_to?(:close)
250
+ @response.close if @response && @response.respond_to?(:close)
174
251
  end
175
252
 
253
+ # always true for error responses.
176
254
  def finished?
177
255
  true
178
256
  end
179
257
 
258
+ # raises the wrapped exception.
180
259
  def raise_for_status
181
260
  raise @error
182
261
  end
@@ -73,7 +73,7 @@ class HTTPX::Selector
73
73
  readers, writers = IO.select(r, w, nil, interval)
74
74
 
75
75
  if readers.nil? && writers.nil? && interval
76
- [*r, *w].each { |io| io.raise_timeout_error(interval) }
76
+ [*r, *w].each { |io| io.handle_socket_timeout(interval) }
77
77
  return
78
78
  end
79
79
  rescue IOError, SystemCallError
@@ -110,7 +110,7 @@ class HTTPX::Selector
110
110
  end
111
111
 
112
112
  unless result || interval.nil?
113
- io.raise_timeout_error(interval)
113
+ io.handle_socket_timeout(interval)
114
114
  return
115
115
  end
116
116
  # raise HTTPX::TimeoutError.new(interval, "timed out while waiting on select")