httpx 0.6.4 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
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