httpx 1.2.1 → 1.2.3

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: 7e5ee54988be76a44ae512da359d83c502f8a43073f244a116a8fdc45fa7b87d
4
- data.tar.gz: e3c08652a8d08eadbd1ef14b20005f93ff4131a712f8234c3eab94c7fce07167
3
+ metadata.gz: 8803154870d8bd0f45f67ce543072fcc42d789400ca0c9251d3ea99f5f214562
4
+ data.tar.gz: 87024f70caa91f93711b6a185a8e3dc7b8987d695472abd13a5a4cb92243d37c
5
5
  SHA512:
6
- metadata.gz: 58f16e523d23215d89a8c873a5ce12491b52726073c334c4d9800e17e40dca8111ad43ab2467c37939a19bebbaa000c8db144fdbba87cc3d22cb699687df6699
7
- data.tar.gz: 64dd9bb70af4173339019b62fa9f54fdf3f22c4bf593b51fb3de624844ac8a599a51b49cae10623aee8b8cff24af4dee69e39bedfec7da3d1ae229d733632e9c
6
+ metadata.gz: ba28ac993c5b17d4d13db24240214a40cfbae5eac5fad40e6420e42725356a289ee33fcb02492bc382d2c26ce93a0696acf7f5f8d64ddf430136ee829f717b70
7
+ data.tar.gz: 93c174e3d210681f1c76127f7a3a69adf43d8a5b3c31432ae0b6e08abd96ca7d189399081efeed710f8c43566e3290931d04b2c38df7de0251508933b2fca129
@@ -0,0 +1,10 @@
1
+ # 1.2.2
2
+
3
+ ## Bugfixes
4
+
5
+ * only raise "unknown option" error when option is not supported, not anymore when error happens in the setup of a support option.
6
+ * usage of `HTTPX::Session#wrap` within a thread with other sessions using the `:persistent` plugin won't inadvertedly terminate its open connections.
7
+ * terminate connections on `IOError` (`SocketError` does not cover them).
8
+ * terminate connections on HTTP/2 protocol and handshake errors, which happen during establishment or termination of a HTTP/2 connection (they were being previously kept around, although they'd irrecoverable).
9
+ * `:oauth` plugin: fixing check preventing the OAuth metadata server integration path to be exercised.
10
+ * fix instantiation of the options headers object with the wrong headers class.
@@ -0,0 +1,16 @@
1
+ # 1.2.3
2
+
3
+ ## Improvements
4
+
5
+ * `:retries` plugin: allow `:max_retries` set to 0 (allows for a soft disable of retries when using the faraday adapter).
6
+
7
+ ## Bugfixes
8
+
9
+ * `:oauth` plugin: fix for default auth method being ignored when setting grant type and scope as options only.
10
+ * ensure happy eyeballs-initiated cloned connections also set session callbacks (caused issues when server would respond with a 421 response, an event requiring a valid internal callback).
11
+ * native resolver cleanly transitions from tcp to udp after truncated DNS query (causing issues on follow-up CNAME resolution).
12
+ * elapsing timeouts now guard against mutation of callbacks while looping (prevents skipping callbacks in situations where a previous one would remove itself from the collection).
13
+
14
+ ## Chore
15
+
16
+ * datadog adapter: do not call `.lazy` on options (avoids deprecation warning, to be removed in ddtrace 2.0)
@@ -169,14 +169,14 @@ module Datadog::Tracing
169
169
  "httpx"
170
170
  )
171
171
  end
172
- o.lazy
172
+ o.lazy unless Gem::Version.new(DDTrace::VERSION::STRING) >= Gem::Version.new("1.13.0")
173
173
  end
174
174
  else
175
175
  option :service_name do |o|
176
176
  o.default do
177
177
  ENV.fetch("DD_TRACE_HTTPX_SERVICE_NAME", "httpx")
178
178
  end
179
- o.lazy
179
+ o.lazy unless Gem::Version.new(DDTrace::VERSION::STRING) >= Gem::Version.new("1.13.0")
180
180
  end
181
181
  end
182
182
 
@@ -522,14 +522,15 @@ module HTTPX
522
522
  Errno::ENETUNREACH,
523
523
  Errno::EPIPE,
524
524
  Errno::ENOENT,
525
- SocketError => e
525
+ SocketError,
526
+ IOError => e
526
527
  # connect errors, exit gracefully
527
528
  error = ConnectionError.new(e.message)
528
529
  error.set_backtrace(e.backtrace)
529
530
  connecting? && callbacks_for?(:connect_error) ? emit(:connect_error, error) : handle_error(error)
530
531
  @state = :closed
531
532
  emit(:close)
532
- rescue TLSError => e
533
+ rescue TLSError, HTTP2Next::Error::ProtocolError, HTTP2Next::Error::HandshakeError => e
533
534
  # connect errors, exit gracefully
534
535
  handle_error(e)
535
536
  connecting? && callbacks_for?(:connect_error) ? emit(:connect_error, e) : handle_error(e)
data/lib/httpx/io/tcp.rb CHANGED
@@ -78,7 +78,8 @@ module HTTPX
78
78
  rescue Errno::ECONNREFUSED,
79
79
  Errno::EADDRNOTAVAIL,
80
80
  Errno::EHOSTUNREACH,
81
- SocketError => e
81
+ SocketError,
82
+ IOError => e
82
83
  raise e if @ip_index <= 0
83
84
 
84
85
  log { "failed connecting to #{@ip} (#{e.message}), trying next..." }
data/lib/httpx/options.rb CHANGED
@@ -47,13 +47,13 @@ module HTTPX
47
47
  write_timeout: WRITE_TIMEOUT,
48
48
  request_timeout: REQUEST_TIMEOUT,
49
49
  },
50
+ :headers_class => Class.new(Headers),
50
51
  :headers => {},
51
52
  :window_size => WINDOW_SIZE,
52
53
  :buffer_size => BUFFER_SIZE,
53
54
  :body_threshold_size => MAX_BODY_THRESHOLD_SIZE,
54
55
  :request_class => Class.new(Request),
55
56
  :response_class => Class.new(Response),
56
- :headers_class => Class.new(Headers),
57
57
  :request_body_class => Class.new(Request::Body),
58
58
  :response_body_class => Class.new(Response::Body),
59
59
  :connection_class => Class.new(Connection),
@@ -154,7 +154,7 @@ module HTTPX
154
154
  end
155
155
 
156
156
  def option_headers(value)
157
- Headers.new(value)
157
+ headers_class.new(value)
158
158
  end
159
159
 
160
160
  def option_timeout(value)
@@ -342,12 +342,11 @@ module HTTPX
342
342
  defaults.each do |k, v|
343
343
  next if v.nil?
344
344
 
345
- begin
346
- value = __send__(:"option_#{k}", v)
347
- instance_variable_set(:"@#{k}", value)
348
- rescue NoMethodError
349
- raise Error, "unknown option: #{k}"
350
- end
345
+ option_method_name = :"option_#{k}"
346
+ raise Error, "unknown option: #{k}" unless respond_to?(option_method_name)
347
+
348
+ value = __send__(option_method_name, v)
349
+ instance_variable_set(:"@#{k}", value)
351
350
  end
352
351
  end
353
352
  end
@@ -16,7 +16,7 @@ module HTTPX
16
16
  SUPPORTED_AUTH_METHODS = %w[client_secret_basic client_secret_post].freeze
17
17
 
18
18
  class OAuthSession
19
- attr_reader :token_endpoint_auth_method, :grant_type, :client_id, :client_secret, :access_token, :refresh_token, :scope
19
+ attr_reader :grant_type, :client_id, :client_secret, :access_token, :refresh_token, :scope
20
20
 
21
21
  def initialize(
22
22
  issuer:,
@@ -28,7 +28,7 @@ module HTTPX
28
28
  token_endpoint: nil,
29
29
  response_type: nil,
30
30
  grant_type: nil,
31
- token_endpoint_auth_method: "client_secret_basic"
31
+ token_endpoint_auth_method: nil
32
32
  )
33
33
  @issuer = URI(issuer)
34
34
  @client_id = client_id
@@ -43,10 +43,10 @@ module HTTPX
43
43
  end
44
44
  @access_token = access_token
45
45
  @refresh_token = refresh_token
46
- @token_endpoint_auth_method = String(token_endpoint_auth_method)
46
+ @token_endpoint_auth_method = String(token_endpoint_auth_method) if token_endpoint_auth_method
47
47
  @grant_type = grant_type || (@refresh_token ? "refresh_token" : "client_credentials")
48
48
 
49
- unless SUPPORTED_AUTH_METHODS.include?(@token_endpoint_auth_method)
49
+ unless @token_endpoint_auth_method.nil? || SUPPORTED_AUTH_METHODS.include?(@token_endpoint_auth_method)
50
50
  raise Error, "#{@token_endpoint_auth_method} is not a supported auth method"
51
51
  end
52
52
 
@@ -59,10 +59,14 @@ module HTTPX
59
59
  @token_endpoint || "#{@issuer}/token"
60
60
  end
61
61
 
62
+ def token_endpoint_auth_method
63
+ @token_endpoint_auth_method || "client_secret_basic"
64
+ end
65
+
62
66
  def load(http)
63
- return unless @token_endpoint && @token_endpoint_auth_method && @grant_type && @scope
67
+ return if @grant_type && @scope
64
68
 
65
- metadata = http.get("#{issuer}/.well-known/oauth-authorization-server").raise_for_status.json
69
+ metadata = http.get("#{@issuer}/.well-known/oauth-authorization-server").raise_for_status.json
66
70
 
67
71
  @token_endpoint = metadata["token_endpoint"]
68
72
  @scope = metadata["scopes_supported"]
@@ -70,6 +74,7 @@ module HTTPX
70
74
  @token_endpoint_auth_method = Array(metadata["token_endpoint_auth_methods_supported"]).find do |am|
71
75
  SUPPORTED_AUTH_METHODS.include?(am)
72
76
  end
77
+ nil
73
78
  end
74
79
 
75
80
  def merge(other)
@@ -122,11 +127,11 @@ module HTTPX
122
127
 
123
128
  # auth
124
129
  case oauth_session.token_endpoint_auth_method
125
- when "client_secret_basic"
126
- headers["authorization"] = Authentication::Basic.new(oauth_session.client_id, oauth_session.client_secret).authenticate
127
130
  when "client_secret_post"
128
131
  form_post["client_id"] = oauth_session.client_id
129
132
  form_post["client_secret"] = oauth_session.client_secret
133
+ when "client_secret_basic"
134
+ headers["authorization"] = Authentication::Basic.new(oauth_session.client_id, oauth_session.client_secret).authenticate
130
135
  end
131
136
 
132
137
  case grant_type
@@ -58,7 +58,7 @@ module HTTPX
58
58
 
59
59
  def option_max_retries(value)
60
60
  num = Integer(value)
61
- raise TypeError, ":max_retries must be positive" unless num.positive?
61
+ raise TypeError, ":max_retries must be positive" unless num >= 0
62
62
 
63
63
  num
64
64
  end
data/lib/httpx/pool.rb CHANGED
@@ -19,6 +19,17 @@ module HTTPX
19
19
  @connections = []
20
20
  end
21
21
 
22
+ def wrap
23
+ connections = @connections
24
+ @connections = []
25
+
26
+ begin
27
+ yield self
28
+ ensure
29
+ @connections.unshift(*connections)
30
+ end
31
+ end
32
+
22
33
  def empty?
23
34
  @connections.empty?
24
35
  end
@@ -168,6 +179,7 @@ module HTTPX
168
179
  connection.once(:connect_error) do |err|
169
180
  if new_connection.connecting?
170
181
  new_connection.merge(connection)
182
+ connection.emit(:cloned, new_connection)
171
183
  connection.force_reset
172
184
  else
173
185
  connection.__send__(:handle_error, err)
@@ -184,6 +196,7 @@ module HTTPX
184
196
  if connection.connecting?
185
197
  # main connection has the requests
186
198
  connection.merge(new_connection)
199
+ new_connection.emit(:cloned, connection)
187
200
  new_connection.force_reset
188
201
  else
189
202
  new_connection.__send__(:handle_error, err)
data/lib/httpx/request.rb CHANGED
@@ -61,7 +61,7 @@ module HTTPX
61
61
  @uri = origin.merge("#{base_path}#{@uri}")
62
62
  end
63
63
 
64
- @headers = @options.headers_class.new(@options.headers)
64
+ @headers = @options.headers.dup
65
65
  @headers["user-agent"] ||= USER_AGENT
66
66
  @headers["accept"] ||= "*/*"
67
67
 
@@ -187,10 +187,10 @@ module HTTPX
187
187
  next unless @large_packet.full?
188
188
 
189
189
  parse(@large_packet.to_s)
190
-
191
190
  @socket_type = @resolver_options.fetch(:socket_type, :udp)
192
191
  @large_packet = nil
193
- transition(:closed)
192
+ transition(:idle)
193
+ transition(:open)
194
194
  return
195
195
  else
196
196
  size = @read_buffer[0, 2].unpack1("n")
@@ -7,10 +7,18 @@ 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
10
+ # Defines a HTTP response is handled internally, with a few properties exposed as attributes.
11
+ #
12
+ # It delegates the following methods to the corresponding HTTPX::Request:
13
+ #
14
+ # * HTTPX::Request#uri
15
+ # * HTTPX::Request#peer_address
16
+ #
17
+ # It implements (indirectly, via the +body+) the IO write protocol to internally buffer payloads.
18
+ #
19
+ # It implements the IO reader protocol in order for users to buffer/stream it, acts as an enumerable
13
20
  # (of payload chunks).
21
+ #
14
22
  class Response
15
23
  extend Forwardable
16
24
  include Callbacks
@@ -21,7 +29,13 @@ module HTTPX
21
29
  # an HTTPX::Headers object containing the response HTTP headers.
22
30
  attr_reader :headers
23
31
 
24
- # a HTTPX::Response::Body object wrapping the response body.
32
+ # a HTTPX::Response::Body object wrapping the response body. The following methods are delegated to it:
33
+ #
34
+ # * HTTPX::Response::Body#to_s
35
+ # * HTTPX::Response::Body#to_str
36
+ # * HTTPX::Response::Body#read
37
+ # * HTTPX::Response::Body#copy_to
38
+ # * HTTPX::Response::Body#close
25
39
  attr_reader :body
26
40
 
27
41
  # The HTTP protocol version used to fetch the response.
data/lib/httpx/session.rb CHANGED
@@ -28,13 +28,15 @@ module HTTPX
28
28
  # http.get("https://wikipedia.com")
29
29
  # end # wikipedia connection closes here
30
30
  def wrap
31
- begin
32
- prev_persistent = @persistent
33
- @persistent = true
34
- yield self
35
- ensure
36
- @persistent = prev_persistent
37
- close unless @persistent
31
+ prev_persistent = @persistent
32
+ @persistent = true
33
+ pool.wrap do
34
+ begin
35
+ yield self
36
+ ensure
37
+ @persistent = prev_persistent
38
+ close unless @persistent
39
+ end
38
40
  end
39
41
  end
40
42
 
@@ -136,7 +138,7 @@ module HTTPX
136
138
 
137
139
  # sets the callbacks on the +connection+ required to process certain specific
138
140
  # connection lifecycle events which deal with request rerouting.
139
- def set_connection_callbacks(connection, connections, options)
141
+ def set_connection_callbacks(connection, connections, options, cloned: false)
140
142
  connection.only(:misdirected) do |misdirected_request|
141
143
  other_connection = connection.create_idle(ssl: { alpn_protocols: %w[http/1.1] })
142
144
  other_connection.merge(connection)
@@ -152,6 +154,10 @@ module HTTPX
152
154
  other_connection = build_altsvc_connection(connection, connections, alt_origin, origin, alt_params, options)
153
155
  connections << other_connection if other_connection
154
156
  end
157
+ connection.only(:cloned) do |cloned_conn|
158
+ set_connection_callbacks(cloned_conn, connections, options, cloned: true)
159
+ connections << cloned_conn
160
+ end unless cloned
155
161
  end
156
162
 
157
163
  # returns an HTTPX::Connection for the negotiated Alternative Service (or none).
data/lib/httpx/timers.rb CHANGED
@@ -97,7 +97,10 @@ module HTTPX
97
97
  def elapse(elapsed)
98
98
  @interval -= elapsed
99
99
 
100
- @callbacks.each(&:call) if @interval <= 0
100
+ if @interval <= 0
101
+ cb = @callbacks.dup
102
+ cb.each(&:call)
103
+ end
101
104
 
102
105
  @interval
103
106
  end
data/lib/httpx/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
- VERSION = "1.2.1"
4
+ VERSION = "1.2.3"
5
5
  end
@@ -15,8 +15,6 @@ module HTTPX
15
15
  SUPPORTED_AUTH_METHODS: ::Array[token_auth_method]
16
16
 
17
17
  class OAuthSession
18
- attr_reader token_endpoint_auth_method: token_auth_method
19
-
20
18
  attr_reader grant_type: grant_type
21
19
 
22
20
  attr_reader client_id: String
@@ -33,6 +31,8 @@ module HTTPX
33
31
 
34
32
  def token_endpoint: () -> String
35
33
 
34
+ def token_endpoint_auth_method: () -> token_auth_method
35
+
36
36
  def load: (Session http) -> void
37
37
 
38
38
  def merge: (instance | Hash[untyped, untyped] other) -> instance
data/sig/pool.rbs CHANGED
@@ -7,6 +7,8 @@ module HTTPX
7
7
  @selector: Selector
8
8
  @connections: Array[Connection]
9
9
 
10
+ def wrap: () { (instance) -> void } -> void
11
+
10
12
  def empty?: () -> void
11
13
 
12
14
  def next_tick: () -> void
data/sig/session.rbs CHANGED
@@ -31,7 +31,7 @@ module HTTPX
31
31
 
32
32
  def send_request: (Request request, Array[Connection] connections, ?Options options) -> void
33
33
 
34
- def set_connection_callbacks: (Connection connection, Array[Connection] connections, Options options) -> void
34
+ def set_connection_callbacks: (Connection connection, Array[Connection] connections, Options options, ?cloned: bool) -> void
35
35
 
36
36
  def set_request_callbacks: (Request request) -> void
37
37
 
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: 1.2.1
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-13 00:00:00.000000000 Z
11
+ date: 2024-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2-next
@@ -139,6 +139,8 @@ extra_rdoc_files:
139
139
  - doc/release_notes/1_1_5.md
140
140
  - doc/release_notes/1_2_0.md
141
141
  - doc/release_notes/1_2_1.md
142
+ - doc/release_notes/1_2_2.md
143
+ - doc/release_notes/1_2_3.md
142
144
  files:
143
145
  - LICENSE.txt
144
146
  - README.md
@@ -249,6 +251,8 @@ files:
249
251
  - doc/release_notes/1_1_5.md
250
252
  - doc/release_notes/1_2_0.md
251
253
  - doc/release_notes/1_2_1.md
254
+ - doc/release_notes/1_2_2.md
255
+ - doc/release_notes/1_2_3.md
252
256
  - lib/httpx.rb
253
257
  - lib/httpx/adapters/datadog.rb
254
258
  - lib/httpx/adapters/faraday.rb