httpx 0.6.4 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8a8f66dc2833078c5d718a91b0aa5ab0f3cfd0ddfa021ddebe491dc8a74cda1
4
- data.tar.gz: b722b06b29af3a535efdc5da32298c358b5cb91ab248224fe21bc5f15982cbfb
3
+ metadata.gz: 54a10e717268eab1bd790ceb5488f7641814e96f0edc7ff2252d020a73f956d4
4
+ data.tar.gz: fac249b2c424c310e8535bdd8940dfeec194b5438e30876da6a3875f349d49ab
5
5
  SHA512:
6
- metadata.gz: c2a70d09852cf6612b50cf13fa54cdb71111bec0583f12830d58a5e042b0dae316e84d3e4b4db132bad77cda88fefd7d7cdd3c6b9ab288c08fdc573b8ff2e3fb
7
- data.tar.gz: fd164d361e5e9b3d7c7439567c014a748c6eedb4b1887ff20213f653ea7234ca5567cd96bc71d651637049bf6405751f46fe423638ae1b820dac4767b2434fc9
6
+ metadata.gz: 044c55f050be59ec7ef78bde8529b1957d120538c89d1488991b07d87cc60b34c66999861fe48b01719e712dd7ab1f03f349890e4ccc074303788b30798a5a90
7
+ data.tar.gz: 0a6b3a24a7d35e7cba39df0b58519b15c15361a96a2e458a1a0bab890a62922ed0cb34881cc506031d8be4a95505444e1401f4570f5d5286372baea548d4b2be
@@ -254,8 +254,7 @@ module HTTPX
254
254
  end
255
255
 
256
256
  def send_pending
257
- while !@write_buffer.full? && (req_args = @pending.shift)
258
- request = req_args
257
+ while !@write_buffer.full? && (request = @pending.shift)
259
258
  parser.send(request)
260
259
  end
261
260
  end
@@ -368,7 +367,7 @@ module HTTPX
368
367
  end
369
368
 
370
369
  parser.handle_error(error) if @parser && parser.respond_to?(:handle_error)
371
- @pending.each do |request|
370
+ while (request = @pending.shift)
372
371
  request.emit(:response, ErrorResponse.new(request, error, @options))
373
372
  end
374
373
  end
@@ -24,8 +24,18 @@ module HTTPX
24
24
  true
25
25
  end
26
26
 
27
- def close
28
- @io.close
27
+ if RUBY_VERSION < "2.2"
28
+ # :nocov:
29
+ def close
30
+ @io.close
31
+ rescue StandardError
32
+ nil
33
+ end
34
+ # :nocov:
35
+ else
36
+ def close
37
+ @io.close
38
+ end
29
39
  end
30
40
 
31
41
  def write(buffer)
@@ -61,6 +61,7 @@ module HTTPX
61
61
  :transport_options => nil,
62
62
  :persistent => false,
63
63
  :resolver_class => (ENV["HTTPX_RESOLVER"] || :native).to_sym,
64
+ :resolver_options => { cache: true },
64
65
  }
65
66
 
66
67
  defaults.merge!(options)
@@ -204,6 +204,16 @@ module HTTPX
204
204
  transition(:closed)
205
205
  emit(:close)
206
206
  end
207
+
208
+ def transition(nextstate)
209
+ return super unless @options.proxy
210
+
211
+ case nextstate
212
+ when :closing
213
+ @state = :open if @state == :connecting
214
+ end
215
+ super
216
+ end
207
217
  end
208
218
  end
209
219
  register_plugin :proxy, Proxy
@@ -41,7 +41,7 @@ module HTTPX
41
41
  end
42
42
 
43
43
  def __http_proxy_connect
44
- req, _ = @pending.first
44
+ req = @pending.first
45
45
  # if the first request after CONNECT is to an https address, it is assumed that
46
46
  # all requests in the queue are not only ALL HTTPS, but they also share the certificate,
47
47
  # and therefore, will share the connection.
@@ -55,17 +55,17 @@ module HTTPX
55
55
  end
56
56
  end
57
57
 
58
- def __http_on_connect(_request, response)
58
+ def __http_on_connect(_, response)
59
59
  if response.status == 200
60
- req, _ = @pending.first
60
+ req = @pending.first
61
61
  request_uri = req.uri
62
62
  @io = ProxySSL.new(@io, request_uri, @options)
63
63
  transition(:connected)
64
64
  throw(:called)
65
65
  else
66
- pending = @pending.map(&:first) + @parser.pending
66
+ pending = @pending + @parser.pending
67
67
  while (req = pending.shift)
68
- emit(:response, req, response)
68
+ req.emit(:response, response)
69
69
  end
70
70
  end
71
71
  end
@@ -78,6 +78,8 @@ module HTTPX
78
78
 
79
79
  def set_request_headers(request)
80
80
  super
81
+ proxy_params = @options.proxy
82
+ request.headers["proxy-authorization"] = "Basic #{proxy_params.token_authentication}" if proxy_params.authenticated?
81
83
  request.headers["proxy-connection"] = request.headers["connection"]
82
84
  request.headers.delete("connection")
83
85
  end
@@ -102,10 +104,8 @@ module HTTPX
102
104
  end
103
105
 
104
106
  class ConnectRequest < Request
105
- def initialize(uri, options)
107
+ def initialize(uri, _options)
106
108
  super(:connect, uri, {})
107
- proxy_params = options.proxy
108
- @headers["proxy-authentication"] = "Basic #{proxy_params.token_authentication}" if proxy_params.authenticated?
109
109
  @headers.delete("accept")
110
110
  end
111
111
 
@@ -28,7 +28,7 @@ module HTTPX
28
28
  @io.connect
29
29
  return unless @io.connected?
30
30
 
31
- req, _ = @pending.first
31
+ req = @pending.first
32
32
  return unless req
33
33
 
34
34
  request_uri = req.uri
@@ -51,7 +51,7 @@ module HTTPX
51
51
  def __socks4_on_packet(packet)
52
52
  _version, status, _port, _ip = packet.unpack("CCnN")
53
53
  if status == GRANTED
54
- req, _ = @pending.first
54
+ req = @pending.first
55
55
  request_uri = req.uri
56
56
  @io = ProxySSL.new(@io, request_uri, @options) if request_uri.scheme == "https"
57
57
  transition(:connected)
@@ -52,7 +52,7 @@ module HTTPX
52
52
  when :negotiating
53
53
  return unless @state == :connecting || @state == :authenticating
54
54
 
55
- req, _ = @pending.first
55
+ req = @pending.first
56
56
  request_uri = req.uri
57
57
  @write_buffer << Packet.connect(request_uri)
58
58
  when :connected
@@ -93,7 +93,7 @@ module HTTPX
93
93
  version, reply, = packet.unpack("CC")
94
94
  __socks5_check_version(version)
95
95
  __on_socks5_error("socks5 negotiation error: #{reply}") unless reply == SUCCESS
96
- req, _ = @pending.first
96
+ req = @pending.first
97
97
  request_uri = req.uri
98
98
  @io = ProxySSL.new(@io, request_uri, @options) if request_uri.scheme == "https"
99
99
  transition(:connected)
@@ -121,6 +121,7 @@ module HTTPX
121
121
  rescue Resolv::DNS::DecodeError, JSON::JSONError => e
122
122
  host, connection = @queries.first
123
123
  if @_record_types[host].empty?
124
+ @queries.delete(host)
124
125
  emit_resolve_error(connection, host, e)
125
126
  return
126
127
  end
@@ -129,6 +130,7 @@ module HTTPX
129
130
  host, connection = @queries.first
130
131
  @_record_types[host].shift
131
132
  if @_record_types[host].empty?
133
+ @queries.delete(host)
132
134
  @_record_types.delete(host)
133
135
  emit_resolve_error(connection, host)
134
136
  return
@@ -158,7 +160,7 @@ module HTTPX
158
160
  next unless connection # probably a retried query for which there's an answer
159
161
 
160
162
  @connections.delete(connection)
161
- Resolver.cached_lookup_set(hostname, addresses)
163
+ Resolver.cached_lookup_set(hostname, addresses) if @resolver_options.cache
162
164
  emit_addresses(connection, addresses.map { |addr| addr["data"] })
163
165
  end
164
166
  end
@@ -59,7 +59,7 @@ module HTTPX
59
59
  @_record_types = Hash.new { |types, host| types[host] = @resolver_options.record_types.dup }
60
60
  @connections = []
61
61
  @queries = {}
62
- @read_buffer = Buffer.new(@resolver_options.packet_size)
62
+ @read_buffer = "".b
63
63
  @write_buffer = Buffer.new(@resolver_options.packet_size)
64
64
  @state = :idle
65
65
  end
@@ -90,8 +90,7 @@ module HTTPX
90
90
  consume
91
91
  end
92
92
  nil
93
- rescue Errno::EHOSTUNREACH,
94
- NativeResolveError => e
93
+ rescue Errno::EHOSTUNREACH => e
95
94
  @ns_index += 1
96
95
  if @ns_index < @nameserver.size
97
96
  log(label: "resolver: ") do
@@ -101,25 +100,14 @@ module HTTPX
101
100
  end
102
101
  transition(:idle)
103
102
  else
104
- if e.respond_to?(:connection) &&
105
- e.respond_to?(:host)
106
- emit_resolve_error(e.connection, e.host, e)
107
- else
108
- @queries.each do |host, connection|
109
- emit_resolve_error(connection, host, e)
110
- end
111
- end
103
+ handle_error(e)
112
104
  end
105
+ rescue NativeResolveError => e
106
+ handle_error(e)
113
107
  end
114
108
 
115
109
  def interests
116
- readable = !@read_buffer.full?
117
- writable = !@write_buffer.empty?
118
- if readable
119
- writable ? :rw : :r
120
- else
121
- writable ? :w : :r
122
- end
110
+ !@write_buffer.empty? || @queries.empty? ? :w : :r
123
111
  end
124
112
 
125
113
  def <<(connection)
@@ -168,6 +156,7 @@ module HTTPX
168
156
  @timeouts[host].shift
169
157
  if @timeouts[host].empty?
170
158
  @timeouts.delete(host)
159
+ @connections.delete(connection)
171
160
  raise NativeResolveError.new(connection, host)
172
161
  else
173
162
  connections << connection
@@ -182,7 +171,7 @@ module HTTPX
182
171
  connections.each { |ch| resolve(ch) }
183
172
  end
184
173
 
185
- def dread(wsize = @read_buffer.limit)
174
+ def dread(wsize = @resolver_options.packet_size)
186
175
  loop do
187
176
  siz = @io.read(wsize, @read_buffer)
188
177
  unless siz
@@ -192,7 +181,7 @@ module HTTPX
192
181
  return if siz.zero?
193
182
 
194
183
  log(label: "resolver: ") { "READ: #{siz} bytes..." }
195
- parse(@read_buffer.to_s)
184
+ parse(@read_buffer)
196
185
  end
197
186
  end
198
187
 
@@ -216,6 +205,8 @@ module HTTPX
216
205
  rescue Resolv::DNS::DecodeError => e
217
206
  hostname, connection = @queries.first
218
207
  if @_record_types[hostname].empty?
208
+ @queries.delete(hostname)
209
+ @connections.delete(connection)
219
210
  ex = NativeResolveError.new(connection, hostname, e.message)
220
211
  ex.set_backtrace(e.backtrace)
221
212
  raise ex
@@ -226,7 +217,9 @@ module HTTPX
226
217
  hostname, connection = @queries.first
227
218
  @_record_types[hostname].shift
228
219
  if @_record_types[hostname].empty?
220
+ @queries.delete(hostname)
229
221
  @_record_types.delete(hostname)
222
+ @connections.delete(connection)
230
223
  raise NativeResolveError.new(connection, hostname)
231
224
  end
232
225
  else
@@ -244,7 +237,7 @@ module HTTPX
244
237
  end
245
238
  else
246
239
  @connections.delete(connection)
247
- Resolver.cached_lookup_set(connection.origin.host, addresses)
240
+ Resolver.cached_lookup_set(connection.origin.host, addresses) if @resolver_options.cache
248
241
  emit_addresses(connection, addresses.map { |addr| addr["data"] })
249
242
  end
250
243
  end
@@ -301,5 +294,16 @@ module HTTPX
301
294
  end
302
295
  @state = nextstate
303
296
  end
297
+
298
+ def handle_error(error)
299
+ if error.respond_to?(:connection) &&
300
+ error.respond_to?(:host)
301
+ emit_resolve_error(error.connection, error.host, error)
302
+ else
303
+ @queries.each do |host, connection|
304
+ emit_resolve_error(connection, host, error)
305
+ end
306
+ end
307
+ end
304
308
  end
305
309
  end
@@ -38,7 +38,7 @@ module HTTPX
38
38
  def early_resolve(connection, hostname: connection.origin.host)
39
39
  addresses = connection.addresses ||
40
40
  ip_resolve(hostname) ||
41
- Resolver.cached_lookup(hostname) ||
41
+ (@resolver_options.cache && Resolver.cached_lookup(hostname)) ||
42
42
  system_resolve(hostname)
43
43
  return unless addresses
44
44
 
@@ -58,10 +58,14 @@ module HTTPX
58
58
  end
59
59
 
60
60
  def emit_resolve_error(connection, hostname, ex = nil)
61
+ emit(:error, connection, resolve_error(hostname, ex))
62
+ end
63
+
64
+ def resolve_error(hostname, ex = nil)
61
65
  message = ex ? ex.message : "Can't resolve #{hostname}"
62
66
  error = ResolveError.new(message)
63
67
  error.set_backtrace(ex ? ex.backtrace : caller)
64
- emit(:error, connection, error)
68
+ error
65
69
  end
66
70
  end
67
71
  end
@@ -14,10 +14,13 @@ module HTTPX
14
14
 
15
15
  def initialize(options)
16
16
  @options = Options.new(options)
17
- roptions = @options.resolver_options
17
+ @resolver_options = Resolver::Options.new(@options.resolver_options)
18
18
  @state = :idle
19
- @resolver = Resolv::DNS.new(roptions.nil? ? nil : roptions)
20
- @resolver.timeouts = roptions[:timeouts] if roptions
19
+ resolv_options = @resolver_options.to_h
20
+ timeouts = resolv_options.delete(:timeouts)
21
+ resolv_options.delete(:cache)
22
+ @resolver = Resolv::DNS.new(resolv_options.empty? ? nil : resolv_options)
23
+ @resolver.timeouts = timeouts if timeouts
21
24
  end
22
25
 
23
26
  def closed?
@@ -34,7 +37,7 @@ module HTTPX
34
37
  ip_resolve(hostname) ||
35
38
  system_resolve(hostname) ||
36
39
  @resolver.getaddresses(hostname)
37
- return emit_resolve_error(connection, hostname) if addresses.empty?
40
+ throw(:resolve_error, resolve_error(hostname)) if addresses.empty?
38
41
 
39
42
  emit_addresses(connection, addresses)
40
43
  rescue Errno::EHOSTUNREACH, *RESOLV_ERRORS => e
@@ -152,9 +152,14 @@ module HTTPX
152
152
  request_options = @options.merge(options)
153
153
 
154
154
  requests.each do |request|
155
- connection = find_connection(request, connections, request_options)
156
- connection.send(request)
157
- set_request_timeout(connection, request, request_options)
155
+ error = catch(:resolve_error) do
156
+ connection = find_connection(request, connections, request_options)
157
+ connection.send(request)
158
+ set_request_timeout(connection, request, request_options)
159
+ end
160
+ next unless error.is_a?(ResolveError)
161
+
162
+ request.emit(:response, ErrorResponse.new(request, error, options))
158
163
  end
159
164
 
160
165
  responses = []
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
- VERSION = "0.6.4"
4
+ VERSION = "0.6.5"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-12 00:00:00.000000000 Z
11
+ date: 2020-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2-next