httpx 0.22.4 → 0.23.0

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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/doc/release_notes/0_22_5.md +6 -0
  3. data/doc/release_notes/0_23_0.md +42 -0
  4. data/lib/httpx/adapters/datadog.rb +12 -2
  5. data/lib/httpx/adapters/faraday.rb +1 -1
  6. data/lib/httpx/adapters/sentry.rb +15 -5
  7. data/lib/httpx/adapters/webmock.rb +2 -2
  8. data/lib/httpx/buffer.rb +4 -0
  9. data/lib/httpx/callbacks.rb +3 -3
  10. data/lib/httpx/chainable.rb +4 -4
  11. data/lib/httpx/connection/http1.rb +2 -2
  12. data/lib/httpx/connection/http2.rb +2 -3
  13. data/lib/httpx/connection.rb +31 -11
  14. data/lib/httpx/io/udp.rb +2 -0
  15. data/lib/httpx/io/unix.rb +1 -5
  16. data/lib/httpx/io.rb +0 -10
  17. data/lib/httpx/options.rb +16 -2
  18. data/lib/httpx/plugins/authentication/digest.rb +1 -1
  19. data/lib/httpx/plugins/aws_sdk_authentication.rb +1 -3
  20. data/lib/httpx/plugins/aws_sigv4.rb +1 -1
  21. data/lib/httpx/plugins/compression/brotli.rb +4 -4
  22. data/lib/httpx/plugins/compression/deflate.rb +12 -7
  23. data/lib/httpx/plugins/compression/gzip.rb +7 -5
  24. data/lib/httpx/plugins/compression.rb +9 -8
  25. data/lib/httpx/plugins/digest_authentication.rb +1 -4
  26. data/lib/httpx/plugins/follow_redirects.rb +1 -1
  27. data/lib/httpx/plugins/grpc/message.rb +3 -1
  28. data/lib/httpx/plugins/grpc.rb +3 -3
  29. data/lib/httpx/plugins/h2c.rb +5 -9
  30. data/lib/httpx/plugins/internal_telemetry.rb +16 -0
  31. data/lib/httpx/plugins/multipart.rb +14 -2
  32. data/lib/httpx/plugins/proxy/http.rb +4 -4
  33. data/lib/httpx/plugins/proxy.rb +65 -31
  34. data/lib/httpx/plugins/response_cache.rb +2 -2
  35. data/lib/httpx/plugins/retries.rb +49 -2
  36. data/lib/httpx/plugins/upgrade/h2.rb +3 -3
  37. data/lib/httpx/plugins/upgrade.rb +4 -7
  38. data/lib/httpx/plugins/webdav.rb +7 -7
  39. data/lib/httpx/pool.rb +7 -3
  40. data/lib/httpx/request.rb +23 -13
  41. data/lib/httpx/resolver/https.rb +37 -20
  42. data/lib/httpx/resolver/multi.rb +1 -6
  43. data/lib/httpx/resolver/native.rb +128 -36
  44. data/lib/httpx/resolver.rb +26 -14
  45. data/lib/httpx/response.rb +14 -16
  46. data/lib/httpx/session.rb +1 -0
  47. data/lib/httpx/transcoder/body.rb +0 -1
  48. data/lib/httpx/transcoder/chunker.rb +0 -1
  49. data/lib/httpx/transcoder/form.rb +0 -1
  50. data/lib/httpx/transcoder/json.rb +0 -1
  51. data/lib/httpx/transcoder/xml.rb +0 -1
  52. data/lib/httpx/transcoder.rb +0 -2
  53. data/lib/httpx/version.rb +1 -1
  54. data/lib/httpx.rb +0 -1
  55. data/sig/buffer.rbs +1 -0
  56. data/sig/chainable.rbs +3 -3
  57. data/sig/connection.rbs +17 -6
  58. data/sig/errors.rbs +9 -0
  59. data/sig/httpx.rbs +3 -3
  60. data/sig/io/ssl.rbs +17 -0
  61. data/sig/io/tcp.rbs +57 -0
  62. data/sig/io/udp.rbs +20 -0
  63. data/sig/io/unix.rbs +10 -0
  64. data/sig/options.rbs +5 -1
  65. data/sig/plugins/compression.rbs +6 -2
  66. data/sig/plugins/cookies/jar.rbs +2 -2
  67. data/sig/plugins/grpc.rbs +3 -3
  68. data/sig/plugins/h2c.rbs +1 -1
  69. data/sig/plugins/proxy.rbs +1 -5
  70. data/sig/plugins/response_cache.rbs +1 -1
  71. data/sig/plugins/retries.rbs +28 -8
  72. data/sig/plugins/upgrade.rbs +5 -3
  73. data/sig/request.rbs +6 -2
  74. data/sig/resolver/https.rbs +3 -1
  75. data/sig/resolver/native.rbs +7 -2
  76. data/sig/resolver/resolver.rbs +0 -2
  77. data/sig/resolver/system.rbs +2 -0
  78. data/sig/resolver.rbs +8 -4
  79. data/sig/response.rbs +6 -2
  80. data/sig/session.rbs +10 -10
  81. data/sig/transcoder/xml.rbs +1 -1
  82. data/sig/transcoder.rbs +4 -5
  83. metadata +11 -5
  84. data/lib/httpx/registry.rb +0 -85
  85. data/sig/registry.rbs +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d5e3e33caae5726e0c7630721296abac27073ed1fc071a7bb8c9467a2b1b2e0
4
- data.tar.gz: f4344aee8002ecbe64d6e3321e1ca9f18507e2fd70223890211e05ab15967479
3
+ metadata.gz: 71f84ab5eb126b7c22ceeabf6ef36935e678376ad79e3585a1c8af0cdadcb36c
4
+ data.tar.gz: 98169826112b92768e6592ec9dcc5a0ebf0dcc34f063a4480d17b4ee4bc3f345
5
5
  SHA512:
6
- metadata.gz: 9c42940a7467f91f66779bdf26b83043fb99b17033d69cee7d7656946abc03a064f1b9952889b3c783b757429d5cc6d476575ff9ab347524738152f846c3ea91
7
- data.tar.gz: 6199caed20de123a10af893a85c2657cc4b4bfb6645592a5155743e74a37ff754d3fcf404c8bb28582bead974b35c6f872d40d8b5ac77806bdc4b34992847e7a
6
+ metadata.gz: 3ebd7512c81d95e87284d5a622d473df66a618597b502eccb17cb7ec738364f46d2dec85b1b63940b6182356ccd11caaef0867f56f671320d3a9f9c04e6ad47b
7
+ data.tar.gz: e98bb305329b8982414eb95d2455ef436703ba328175ddd383170c68463aa7d1b83721ac9ffd74fdd91190b0ce055668eac8c67c23648ac7493dfdc01d96e3a6
@@ -0,0 +1,6 @@
1
+ # 0.22.5
2
+
3
+ ## Bugfixes
4
+
5
+ * `datadog` and `sentry` integrations did not account for `Connection#send` being possibly called multiple times (something possible for connection coalescing, max requests exhaustion, or Happy Eyeballs 2), and were registering multiple `on(:response)` callbacks. Requests are now marked when decorated the first time.
6
+ * Happy Eyeballs handshake "connect errors" routine is now taking both name resolution errors, as well as TLS handshake errors, into account, when the handshake fails.
@@ -0,0 +1,42 @@
1
+ # 0.23.0
2
+
3
+ ## Features
4
+
5
+ ### `:retries` plugin: resumable requests
6
+
7
+ The `:retries` plugin will now support scenarios where, if the request being retried supports the `range` header, and a partial response has been already buffered, the retry will resume from there and only download the missing data.
8
+
9
+ #### HTTPX::ErrorResponse#response
10
+
11
+ As a result, ´HTTPX::ErrorResponse#response` has also been introduced; error responses may have an actual response. This happens in cases where the request failed **after** a partial response was initiated.
12
+
13
+ #### `:buffer_size` option
14
+
15
+ A nnew option, `:buffer_size`, can be used to tweak the buffers used by the read/write socket routines (16k by default, you can lower it in memory-constrained environments).
16
+
17
+ ## Improvements
18
+
19
+ ### `:native` resolver falls back to TCP for truncated messages
20
+
21
+ The `:native` resolver will repeat DNS queries to a nameserver via TCP when the first attempt is marked as truncated. This behaviour is both aligned with `getaddrinfo` and the `resolv` standard library.
22
+
23
+ This introduces a new `resolver_options` option, `:socket_type`, which can now be `:tcp` if it is to remain the default.
24
+
25
+ ## Chore
26
+
27
+ ### HTTPX.build_request should receive upcased string (i.e. "GET")
28
+
29
+ Functions which receive an HTTP verb should be given he verb in "upcased string" format now. The usage of symbols is still possible, but a deprecation warning will be emitted, and support will be removed in v1.0.0 .
30
+
31
+ ### Remove HTTPX::Registry
32
+
33
+ These internal registries were a bit magical to use, difficult to debug, not thread-safe, and overall a nuisance when it came to type checking. While there is the possibility that someone was relying on it existing, nothing had ever been publicly documented.
34
+
35
+ ## Bugfixes
36
+
37
+ * fixed proxy discovery using proxy env vars (`HTTPS_PROXY`, `NO_PROXY`...) being enabled/disabled based on first host uused in the session;
38
+ * fixed `:no_proxy` option usage inn the `:proxy` plugin.
39
+ * fixed `webmock` adapter to correctly disable it when `Webmock.disable!` is called.
40
+ * fixed bug in `:digest_authentication` plugin when enabled and no credentials were passed.
41
+ * fixed several bugs in the `sentry` adapter around breadcrumb handling.
42
+ * fixed `:native` resolver candidate calculation by putting absolute domain at the bottom of the list.
@@ -68,7 +68,7 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
68
68
 
69
69
  @request.on(:response, &method(:finish))
70
70
 
71
- verb = @request.verb.to_s.upcase
71
+ verb = @request.verb
72
72
  uri = @request.uri
73
73
 
74
74
  @span = build_span
@@ -158,9 +158,19 @@ module TRACING_MODULE # rubocop:disable Naming/ClassAndModuleCamelCase
158
158
  end
159
159
  end
160
160
 
161
+ module RequestMethods
162
+ def __datadog_enable_trace!
163
+ return super if @__datadog_enable_trace
164
+
165
+ RequestTracer.new(self).call
166
+ @__datadog_enable_trace = true
167
+ end
168
+ end
169
+
161
170
  module ConnectionMethods
162
171
  def send(request)
163
- RequestTracer.new(request).call
172
+ request.__datadog_enable_trace!
173
+
164
174
  super
165
175
  end
166
176
  end
@@ -44,7 +44,7 @@ module Faraday
44
44
  headers: env.request_headers,
45
45
  body: env.body,
46
46
  }
47
- [meth, env.url, request_options]
47
+ [meth.to_s.upcase, env.url, request_options]
48
48
  end
49
49
 
50
50
  def options_from_env(env)
@@ -43,8 +43,8 @@ module HTTPX::Plugins
43
43
 
44
44
  request_info = extract_request_info(req)
45
45
 
46
- data = if response.is_a?(HTTPX::ErrorResponse)
47
- { error: res.message, **request_info }
46
+ data = if res.is_a?(HTTPX::ErrorResponse)
47
+ { error: res.error.message, **request_info }
48
48
  else
49
49
  { status: res.status, **request_info }
50
50
  end
@@ -64,7 +64,7 @@ module HTTPX::Plugins
64
64
  request_info = extract_request_info(req)
65
65
  sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
66
66
  if res.is_a?(HTTPX::ErrorResponse)
67
- sentry_span.set_data(:error, res.message)
67
+ sentry_span.set_data(:error, res.error.message)
68
68
  else
69
69
  sentry_span.set_data(:status, res.status)
70
70
  end
@@ -75,7 +75,7 @@ module HTTPX::Plugins
75
75
  uri = req.uri
76
76
 
77
77
  result = {
78
- method: req.verb.to_s.upcase,
78
+ method: req.verb,
79
79
  }
80
80
 
81
81
  if ::Sentry.configuration.send_default_pii
@@ -89,9 +89,19 @@ module HTTPX::Plugins
89
89
  end
90
90
  end
91
91
 
92
+ module RequestMethods
93
+ def __sentry_enable_trace!
94
+ return super if @__sentry_enable_trace
95
+
96
+ Tracer.call(self)
97
+ @__sentry_enable_trace = true
98
+ end
99
+ end
100
+
92
101
  module ConnectionMethods
93
102
  def send(request)
94
- Tracer.call(request)
103
+ request.__sentry_enable_trace!
104
+
95
105
  super
96
106
  end
97
107
  end
@@ -23,7 +23,7 @@ module WebMock
23
23
  uri.path = uri.normalized_path.gsub("[^:]//", "/")
24
24
 
25
25
  WebMock::RequestSignature.new(
26
- request.verb,
26
+ request.verb.downcase.to_sym,
27
27
  uri.to_s,
28
28
  body: request.body.each.to_a.join,
29
29
  headers: request.headers.to_h
@@ -122,7 +122,7 @@ module WebMock
122
122
 
123
123
  class << self
124
124
  def enable!
125
- @original_session = HTTPX::Session
125
+ @original_session ||= HTTPX::Session
126
126
 
127
127
  webmock_session = HTTPX.plugin(Plugin)
128
128
 
data/lib/httpx/buffer.rb CHANGED
@@ -31,6 +31,10 @@ module HTTPX
31
31
  @buffer.bytesize >= @limit
32
32
  end
33
33
 
34
+ def capacity
35
+ @limit - @buffer.bytesize
36
+ end
37
+
34
38
  def shift!(fin)
35
39
  @buffer = @buffer.byteslice(fin..-1) || "".b
36
40
  end
@@ -22,12 +22,12 @@ module HTTPX
22
22
  callbacks(type).delete_if { |pr| :delete == pr.call(*args) } # rubocop:disable Style/YodaCondition
23
23
  end
24
24
 
25
- protected
26
-
27
25
  def callbacks_for?(type)
28
- @callbacks.key?(type) && !@callbacks[type].empty?
26
+ @callbacks.key?(type) && @callbacks[type].any?
29
27
  end
30
28
 
29
+ protected
30
+
31
31
  def callbacks(type = nil)
32
32
  return @callbacks unless type
33
33
 
@@ -2,11 +2,11 @@
2
2
 
3
3
  module HTTPX
4
4
  module Chainable
5
- %i[head get post put delete trace options connect patch].each do |meth|
5
+ %w[head get post put delete trace options connect patch].each do |meth|
6
6
  class_eval(<<-MOD, __FILE__, __LINE__ + 1)
7
- def #{meth}(*uri, **options) # def get(*uri, **options)
8
- request(:#{meth}, uri, **options) # request(:get, uri, **options)
9
- end # end
7
+ def #{meth}(*uri, **options) # def get(*uri, **options)
8
+ request("#{meth.upcase}", uri, **options) # request("GET", uri, **options)
9
+ end # end
10
10
  MOD
11
11
  end
12
12
 
@@ -106,6 +106,7 @@ module HTTPX
106
106
 
107
107
  def on_headers(h)
108
108
  @request = @requests.first
109
+
109
110
  return if @request.response
110
111
 
111
112
  log(level: 2) { "headers received" }
@@ -312,7 +313,7 @@ module HTTPX
312
313
  end
313
314
 
314
315
  def join_headline(request)
315
- "#{request.verb.to_s.upcase} #{request.path} HTTP/#{@version.join(".")}"
316
+ "#{request.verb} #{request.path} HTTP/#{@version.join(".")}"
316
317
  end
317
318
 
318
319
  def join_headers(request)
@@ -367,5 +368,4 @@ module HTTPX
367
368
  UPCASED[field] || field.split("-").map(&:capitalize).join("-")
368
369
  end
369
370
  end
370
- Connection.register "http/1.1", Connection::HTTP1
371
371
  end
@@ -208,7 +208,7 @@ module HTTPX
208
208
  def set_protocol_headers(request)
209
209
  {
210
210
  ":scheme" => request.scheme,
211
- ":method" => request.verb.to_s.upcase,
211
+ ":method" => request.verb,
212
212
  ":path" => request.path,
213
213
  ":authority" => request.authority,
214
214
  }
@@ -317,7 +317,7 @@ module HTTPX
317
317
  emit(:response, request, response)
318
318
  else
319
319
  response = request.response
320
- if response && response.status == 421
320
+ if response && response.is_a?(Response) && response.status == 421
321
321
  ex = MisdirectedRequestError.new(response)
322
322
  ex.set_backtrace(caller)
323
323
  emit(:error, request, ex)
@@ -412,5 +412,4 @@ module HTTPX
412
412
  end
413
413
  end
414
414
  end
415
- Connection.register "h2", Connection::HTTP2
416
415
  end
@@ -29,7 +29,6 @@ module HTTPX
29
29
  #
30
30
  class Connection
31
31
  extend Forwardable
32
- include Registry
33
32
  include Loggable
34
33
  include Callbacks
35
34
 
@@ -39,8 +38,6 @@ module HTTPX
39
38
  require "httpx/connection/http2"
40
39
  require "httpx/connection/http1"
41
40
 
42
- BUFFER_SIZE = 1 << 14
43
-
44
41
  def_delegator :@io, :closed?
45
42
 
46
43
  def_delegator :@write_buffer, :empty?
@@ -57,15 +54,15 @@ module HTTPX
57
54
  @origin = Utils.to_uri(uri.origin)
58
55
  @options = Options.new(options)
59
56
  @window_size = @options.window_size
60
- @read_buffer = Buffer.new(BUFFER_SIZE)
61
- @write_buffer = Buffer.new(BUFFER_SIZE)
57
+ @read_buffer = Buffer.new(@options.buffer_size)
58
+ @write_buffer = Buffer.new(@options.buffer_size)
62
59
  @pending = []
63
60
  on(:error, &method(:on_error))
64
61
  if @options.io
65
62
  # if there's an already open IO, get its
66
63
  # peer address, and force-initiate the parser
67
64
  transition(:already_open)
68
- @io = IO.registry(@type).new(@origin, nil, @options)
65
+ @io = build_socket
69
66
  parser
70
67
  else
71
68
  transition(:idle)
@@ -84,7 +81,7 @@ module HTTPX
84
81
  if @io
85
82
  @io.add_addresses(addrs)
86
83
  else
87
- @io = IO.registry(@type).new(@origin, addrs, @options)
84
+ @io = build_socket(addrs)
88
85
  end
89
86
  end
90
87
 
@@ -104,7 +101,7 @@ module HTTPX
104
101
  # was the result of coalescing. To prevent blind trust in the case where the
105
102
  # origin came from an ORIGIN frame, we're going to verify the hostname with the
106
103
  # SSL certificate
107
- (@origins.size == 1 || @origin == uri.origin || (@io && @io.verify_hostname(uri.host)))
104
+ (@origins.size == 1 || @origin == uri.origin || (@io.is_a?(SSL) && @io.verify_hostname(uri.host)))
108
105
  ) && @options == options
109
106
  ) || (match_altsvcs?(uri) && match_altsvc_options?(uri, options))
110
107
  end
@@ -118,7 +115,7 @@ module HTTPX
118
115
 
119
116
  (
120
117
  (open? && @origin == connection.origin) ||
121
- !(@io.addresses & connection.addresses).empty?
118
+ !(@io.addresses & (connection.addresses || [])).empty?
122
119
  ) && @options == connection.options
123
120
  end
124
121
 
@@ -453,7 +450,7 @@ module HTTPX
453
450
  end
454
451
 
455
452
  def build_parser(protocol = @io.protocol)
456
- parser = registry(protocol).new(@write_buffer, @options)
453
+ parser = self.class.parser_type(protocol).new(@write_buffer, @options)
457
454
  set_parser_callbacks(parser)
458
455
  parser
459
456
  end
@@ -538,12 +535,13 @@ module HTTPX
538
535
  # connect errors, exit gracefully
539
536
  error = ConnectionError.new(e.message)
540
537
  error.set_backtrace(e.backtrace)
541
- connecting? && callbacks(:connect_error).any? ? emit(:connect_error, error) : handle_error(error)
538
+ connecting? && callbacks_for?(:connect_error) ? emit(:connect_error, error) : handle_error(error)
542
539
  @state = :closed
543
540
  emit(:close)
544
541
  rescue TLSError => e
545
542
  # connect errors, exit gracefully
546
543
  handle_error(e)
544
+ connecting? && callbacks_for?(:connect_error) ? emit(:connect_error, e) : handle_error(e)
547
545
  @state = :closed
548
546
  emit(:close)
549
547
  end
@@ -595,6 +593,17 @@ module HTTPX
595
593
  remove_instance_variable(:@timeout) if defined?(@timeout)
596
594
  end
597
595
 
596
+ def build_socket(addrs = nil)
597
+ transport_type = case @type
598
+ when "tcp" then TCP
599
+ when "ssl" then SSL
600
+ when "unix" then UNIX
601
+ else
602
+ raise Error, "unsupported transport (#{@type})"
603
+ end
604
+ transport_type.new(@origin, addrs, @options)
605
+ end
606
+
598
607
  def on_error(error)
599
608
  if error.instance_of?(TimeoutError)
600
609
 
@@ -663,5 +672,16 @@ module HTTPX
663
672
  error = error_type.new(request, request.response, read_timeout)
664
673
  on_error(error)
665
674
  end
675
+
676
+ class << self
677
+ def parser_type(protocol)
678
+ case protocol
679
+ when "h2" then HTTP2
680
+ when "http/1.1" then HTTP1
681
+ else
682
+ raise Error, "unsupported protocol (##{protocol})"
683
+ end
684
+ end
685
+ end
666
686
  end
667
687
  end
data/lib/httpx/io/udp.rb CHANGED
@@ -78,6 +78,8 @@ module HTTPX
78
78
  return 0 if ret == :wait_readable
79
79
  return if ret.nil?
80
80
 
81
+ log { "READ: #{buffer.bytesize} bytes..." }
82
+
81
83
  buffer.bytesize
82
84
  rescue IOError
83
85
  end
data/lib/httpx/io/unix.rb CHANGED
@@ -1,11 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "forwardable"
4
-
5
3
  module HTTPX
6
4
  class UNIX < TCP
7
- extend Forwardable
8
-
9
5
  using URIExtensions
10
6
 
11
7
  attr_reader :path
@@ -13,7 +9,7 @@ module HTTPX
13
9
  alias_method :host, :path
14
10
 
15
11
  def initialize(origin, addresses, options)
16
- @addresses = addresses
12
+ @addresses = []
17
13
  @hostname = origin.host
18
14
  @state = :idle
19
15
  @options = Options.new(options)
data/lib/httpx/io.rb CHANGED
@@ -5,13 +5,3 @@ require "httpx/io/udp"
5
5
  require "httpx/io/tcp"
6
6
  require "httpx/io/unix"
7
7
  require "httpx/io/ssl"
8
-
9
- module HTTPX
10
- module IO
11
- extend Registry
12
- register "udp", UDP
13
- register "unix", HTTPX::UNIX
14
- register "tcp", TCP
15
- register "ssl", SSL
16
- end
17
- end
data/lib/httpx/options.rb CHANGED
@@ -4,6 +4,7 @@ require "socket"
4
4
 
5
5
  module HTTPX
6
6
  class Options
7
+ BUFFER_SIZE = 1 << 14
7
8
  WINDOW_SIZE = 1 << 14 # 16K
8
9
  MAX_BODY_THRESHOLD_SIZE = (1 << 10) * 112 # 112K
9
10
  CONNECT_TIMEOUT = 60
@@ -41,6 +42,7 @@ module HTTPX
41
42
  },
42
43
  :headers => {},
43
44
  :window_size => WINDOW_SIZE,
45
+ :buffer_size => BUFFER_SIZE,
44
46
  :body_threshold_size => MAX_BODY_THRESHOLD_SIZE,
45
47
  :request_class => Class.new(Request),
46
48
  :response_class => Class.new(Response),
@@ -178,7 +180,19 @@ module HTTPX
178
180
  end
179
181
 
180
182
  def option_window_size(value)
181
- Integer(value)
183
+ value = Integer(value)
184
+
185
+ raise TypeError, ":window_size must be positive" unless value.positive?
186
+
187
+ value
188
+ end
189
+
190
+ def option_buffer_size(value)
191
+ value = Integer(value)
192
+
193
+ raise TypeError, ":buffer_size must be positive" unless value.positive?
194
+
195
+ value
182
196
  end
183
197
 
184
198
  def option_body_threshold_size(value)
@@ -187,7 +201,7 @@ module HTTPX
187
201
 
188
202
  def option_transport(value)
189
203
  transport = value.to_s
190
- raise TypeError, "\#{transport} is an unsupported transport type" unless IO.registry.key?(transport)
204
+ raise TypeError, "#{transport} is an unsupported transport type" unless %w[unix].include?(transport)
191
205
 
192
206
  transport
193
207
  end
@@ -21,7 +21,7 @@ module HTTPX
21
21
  end
22
22
 
23
23
  def authenticate(request, authenticate)
24
- "Digest #{generate_header(request.verb.to_s.upcase, request.path, authenticate)}"
24
+ "Digest #{generate_header(request.verb, request.path, authenticate)}"
25
25
  end
26
26
 
27
27
  private
@@ -20,9 +20,7 @@ module HTTPX
20
20
  true
21
21
  end
22
22
 
23
- def method_missing(*)
24
- nil
25
- end
23
+ def method_missing(*); end
26
24
  end
27
25
 
28
26
  #
@@ -71,7 +71,7 @@ module HTTPX
71
71
  end.join
72
72
 
73
73
  # canonical request
74
- creq = "#{request.verb.to_s.upcase}" \
74
+ creq = "#{request.verb}" \
75
75
  "\n#{request.canonical_path}" \
76
76
  "\n#{request.canonical_query}" \
77
77
  "\n#{canonical_headers}" \
@@ -5,13 +5,13 @@ module HTTPX
5
5
  module Compression
6
6
  module Brotli
7
7
  class << self
8
- def load_dependencies(_klass)
8
+ def load_dependencies(klass)
9
9
  require "brotli"
10
+ klass.plugin(:compression)
10
11
  end
11
12
 
12
- def configure(klass)
13
- klass.plugin(:compression)
14
- klass.default_options.encodings.register "br", self
13
+ def extra_options(options)
14
+ options.merge(encodings: options.encodings.merge("br" => self))
15
15
  end
16
16
  end
17
17
 
@@ -4,14 +4,19 @@ module HTTPX
4
4
  module Plugins
5
5
  module Compression
6
6
  module Deflate
7
- def self.load_dependencies(_klass)
8
- require "stringio"
9
- require "zlib"
10
- end
7
+ class << self
8
+ def load_dependencies(_klass)
9
+ require "stringio"
10
+ require "zlib"
11
+ end
11
12
 
12
- def self.configure(klass)
13
- klass.plugin(:"compression/gzip")
14
- klass.default_options.encodings.register "deflate", self
13
+ def configure(klass)
14
+ klass.plugin(:"compression/gzip")
15
+ end
16
+
17
+ def extra_options(options)
18
+ options.merge(encodings: options.encodings.merge("deflate" => self))
19
+ end
15
20
  end
16
21
 
17
22
  module Deflater
@@ -6,12 +6,14 @@ module HTTPX
6
6
  module Plugins
7
7
  module Compression
8
8
  module GZIP
9
- def self.load_dependencies(*)
10
- require "zlib"
11
- end
9
+ class << self
10
+ def load_dependencies(*)
11
+ require "zlib"
12
+ end
12
13
 
13
- def self.configure(klass)
14
- klass.default_options.encodings.register "gzip", self
14
+ def extra_options(options)
15
+ options.merge(encodings: options.encodings.merge("gzip" => self))
16
+ end
15
17
  end
16
18
 
17
19
  class Deflater
@@ -20,10 +20,7 @@ module HTTPX
20
20
  end
21
21
 
22
22
  def extra_options(options)
23
- encodings = Module.new do
24
- extend Registry
25
- end
26
- options.merge(encodings: encodings)
23
+ options.merge(encodings: {})
27
24
  end
28
25
  end
29
26
 
@@ -36,7 +33,7 @@ module HTTPX
36
33
  end
37
34
 
38
35
  def option_encodings(value)
39
- raise TypeError, ":encodings must be a registry" unless value.respond_to?(:registry)
36
+ raise TypeError, ":encodings must be an Hash" unless value.is_a?(Hash)
40
37
 
41
38
  value
42
39
  end
@@ -49,7 +46,7 @@ module HTTPX
49
46
  if @headers.key?("range")
50
47
  @headers.delete("accept-encoding")
51
48
  else
52
- @headers["accept-encoding"] ||= @options.encodings.registry.keys
49
+ @headers["accept-encoding"] ||= @options.encodings.keys
53
50
  end
54
51
  end
55
52
  end
@@ -65,7 +62,9 @@ module HTTPX
65
62
  @headers.get("content-encoding").each do |encoding|
66
63
  next if encoding == "identity"
67
64
 
68
- @body = Encoder.new(@body, options.encodings.registry(encoding).deflater)
65
+ next unless options.encodings.key?(encoding)
66
+
67
+ @body = Encoder.new(@body, options.encodings[encoding].deflater)
69
68
  end
70
69
  @headers["content-length"] = @body.bytesize unless unbounded_body?
71
70
  end
@@ -95,7 +94,9 @@ module HTTPX
95
94
  @_inflaters = @headers.get("content-encoding").filter_map do |encoding|
96
95
  next if encoding == "identity"
97
96
 
98
- inflater = @options.encodings.registry(encoding).inflater(compressed_length)
97
+ next unless @options.encodings.key?(encoding)
98
+
99
+ inflater = @options.encodings[encoding].inflater(compressed_length)
99
100
  # do not uncompress if there is no decoder available. In fact, we can't reliably
100
101
  # continue decompressing beyond that, so ignore.
101
102
  break unless inflater
@@ -39,10 +39,7 @@ module HTTPX
39
39
  requests.flat_map do |request|
40
40
  digest = request.options.digest
41
41
 
42
- unless digest
43
- super(request)
44
- next
45
- end
42
+ next super(request) unless digest
46
43
 
47
44
  probe_response = wrap { super(request).first }
48
45
 
@@ -103,7 +103,7 @@ module HTTPX
103
103
  max_redirects: max_redirects - 1)
104
104
  end
105
105
 
106
- build_request(:get, redirect_uri, retry_options)
106
+ build_request("GET", redirect_uri, retry_options)
107
107
  end
108
108
 
109
109
  def __get_location_from_response(response)
@@ -47,7 +47,9 @@ module HTTPX
47
47
  data = message.byteslice(5..size + 5 - 1)
48
48
  if compressed == 1
49
49
  encodings.reverse_each do |algo|
50
- inflater = encoders.registry(algo).inflater(size)
50
+ next unless encoders.key?(algo)
51
+
52
+ inflater = encoders[algo].inflater(size)
51
53
  data = inflater.inflate(data)
52
54
  size = data.bytesize
53
55
  end