httpx 0.22.4 → 0.23.0

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