httpx 0.24.6 → 1.0.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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +0 -48
  3. data/README.md +4 -13
  4. data/doc/release_notes/0_24_4.md +3 -3
  5. data/doc/release_notes/1_0_0.md +60 -0
  6. data/lib/httpx/adapters/datadog.rb +28 -97
  7. data/lib/httpx/adapters/faraday.rb +9 -52
  8. data/lib/httpx/adapters/webmock.rb +2 -7
  9. data/lib/httpx/altsvc.rb +4 -22
  10. data/lib/httpx/base64.rb +27 -0
  11. data/lib/httpx/chainable.rb +0 -23
  12. data/lib/httpx/connection.rb +11 -32
  13. data/lib/httpx/domain_name.rb +5 -12
  14. data/lib/httpx/errors.rb +0 -2
  15. data/lib/httpx/extensions.rb +0 -124
  16. data/lib/httpx/io/ssl.rb +26 -59
  17. data/lib/httpx/io/tcp.rb +27 -68
  18. data/lib/httpx/io/udp.rb +13 -48
  19. data/lib/httpx/io/unix.rb +1 -8
  20. data/lib/httpx/loggable.rb +4 -19
  21. data/lib/httpx/options.rb +24 -84
  22. data/lib/httpx/plugins/{authentication → auth}/basic.rb +1 -5
  23. data/lib/httpx/plugins/{authentication → auth}/digest.rb +2 -5
  24. data/lib/httpx/plugins/{authentication → auth}/ntlm.rb +1 -3
  25. data/lib/httpx/plugins/{authentication → auth}/socks5.rb +0 -2
  26. data/lib/httpx/plugins/auth.rb +25 -0
  27. data/lib/httpx/plugins/aws_sigv4.rb +0 -1
  28. data/lib/httpx/plugins/{basic_authentication.rb → basic_auth.rb} +5 -6
  29. data/lib/httpx/plugins/brotli.rb +50 -0
  30. data/lib/httpx/plugins/circuit_breaker/circuit.rb +40 -16
  31. data/lib/httpx/plugins/circuit_breaker/circuit_store.rb +16 -5
  32. data/lib/httpx/plugins/circuit_breaker.rb +11 -4
  33. data/lib/httpx/plugins/cookies/set_cookie_parser.rb +0 -2
  34. data/lib/httpx/plugins/cookies.rb +1 -1
  35. data/lib/httpx/plugins/{digest_authentication.rb → digest_auth.rb} +5 -5
  36. data/lib/httpx/plugins/follow_redirects.rb +21 -24
  37. data/lib/httpx/plugins/grpc/grpc_encoding.rb +82 -0
  38. data/lib/httpx/plugins/grpc/message.rb +7 -39
  39. data/lib/httpx/plugins/grpc.rb +15 -21
  40. data/lib/httpx/plugins/h2c.rb +0 -1
  41. data/lib/httpx/plugins/{ntlm_authentication.rb → ntlm_auth.rb} +5 -5
  42. data/lib/httpx/plugins/oauth.rb +2 -2
  43. data/lib/httpx/plugins/proxy/http.rb +0 -2
  44. data/lib/httpx/plugins/proxy/socks4.rb +0 -4
  45. data/lib/httpx/plugins/proxy/socks5.rb +1 -5
  46. data/lib/httpx/plugins/proxy.rb +3 -32
  47. data/lib/httpx/plugins/retries.rb +3 -4
  48. data/lib/httpx/plugins/stream.rb +4 -6
  49. data/lib/httpx/punycode.rb +9 -291
  50. data/lib/httpx/request/body.rb +145 -0
  51. data/lib/httpx/request.rb +2 -119
  52. data/lib/httpx/resolver/https.rb +1 -1
  53. data/lib/httpx/resolver/native.rb +6 -14
  54. data/lib/httpx/resolver/resolver.rb +1 -1
  55. data/lib/httpx/resolver/system.rb +11 -9
  56. data/lib/httpx/response/body.rb +206 -0
  57. data/lib/httpx/response/buffer.rb +90 -0
  58. data/lib/httpx/response.rb +5 -208
  59. data/lib/httpx/selector.rb +0 -2
  60. data/lib/httpx/session.rb +0 -10
  61. data/lib/httpx/transcoder/body.rb +0 -1
  62. data/lib/httpx/transcoder/deflate.rb +37 -0
  63. data/lib/httpx/transcoder/form.rb +52 -32
  64. data/lib/httpx/transcoder/gzip.rb +74 -0
  65. data/lib/httpx/transcoder/json.rb +2 -4
  66. data/lib/httpx/transcoder/multipart/decoder.rb +139 -0
  67. data/lib/httpx/{plugins → transcoder}/multipart/encoder.rb +3 -3
  68. data/lib/httpx/{plugins → transcoder}/multipart/mime_type_detector.rb +1 -1
  69. data/lib/httpx/{plugins → transcoder}/multipart/part.rb +3 -2
  70. data/lib/httpx/transcoder/multipart.rb +17 -0
  71. data/lib/httpx/transcoder/utils/body_reader.rb +46 -0
  72. data/lib/httpx/transcoder/utils/deflater.rb +72 -0
  73. data/lib/httpx/transcoder/xml.rb +0 -2
  74. data/lib/httpx/transcoder.rb +2 -2
  75. data/lib/httpx/utils.rb +10 -20
  76. data/lib/httpx/version.rb +1 -1
  77. data/lib/httpx.rb +0 -8
  78. data/sig/chainable.rbs +5 -6
  79. data/sig/connection.rbs +0 -1
  80. data/sig/errors.rbs +0 -3
  81. data/sig/httpx.rbs +2 -1
  82. data/sig/io/unix.rbs +1 -1
  83. data/sig/options.rbs +12 -8
  84. data/sig/plugins/{authentication → auth}/basic.rbs +0 -2
  85. data/sig/plugins/auth.rbs +13 -0
  86. data/sig/plugins/{basic_authentication.rbs → basic_auth.rbs} +2 -2
  87. data/sig/plugins/brotli.rbs +22 -0
  88. data/sig/plugins/circuit_breaker.rbs +7 -3
  89. data/sig/plugins/compression.rbs +0 -2
  90. data/sig/plugins/{digest_authentication.rbs → digest_auth.rbs} +2 -2
  91. data/sig/plugins/follow_redirects.rbs +0 -1
  92. data/sig/plugins/grpc/call.rbs +19 -0
  93. data/sig/plugins/grpc/grpc_encoding.rbs +33 -0
  94. data/sig/plugins/grpc/message.rbs +17 -0
  95. data/sig/plugins/grpc.rbs +2 -32
  96. data/sig/plugins/{ntlm_authentication.rbs → ntlm_auth.rbs} +2 -2
  97. data/sig/plugins/oauth.rbs +1 -1
  98. data/sig/plugins/proxy/socks4.rbs +2 -3
  99. data/sig/plugins/proxy/socks5.rbs +0 -1
  100. data/sig/plugins/proxy/ssh.rbs +1 -1
  101. data/sig/plugins/response_cache.rbs +5 -2
  102. data/sig/request/body.rbs +42 -0
  103. data/sig/request.rbs +1 -27
  104. data/sig/resolver/resolver.rbs +1 -1
  105. data/sig/response/body.rbs +52 -0
  106. data/sig/response/buffer.rbs +24 -0
  107. data/sig/response.rbs +0 -39
  108. data/sig/transcoder/body.rbs +4 -3
  109. data/sig/transcoder/deflate.rbs +11 -0
  110. data/sig/transcoder/form.rbs +5 -3
  111. data/sig/transcoder/gzip.rbs +24 -0
  112. data/sig/transcoder/json.rbs +4 -2
  113. data/sig/{plugins → transcoder}/multipart.rbs +3 -10
  114. data/sig/transcoder/utils/body_reader.rbs +15 -0
  115. data/sig/transcoder/utils/deflater.rbs +29 -0
  116. data/sig/transcoder.rbs +18 -2
  117. metadata +50 -34
  118. data/lib/httpx/plugins/authentication.rb +0 -24
  119. data/lib/httpx/plugins/compression/brotli.rb +0 -54
  120. data/lib/httpx/plugins/compression/deflate.rb +0 -54
  121. data/lib/httpx/plugins/compression/gzip.rb +0 -90
  122. data/lib/httpx/plugins/compression.rb +0 -165
  123. data/lib/httpx/plugins/multipart/decoder.rb +0 -137
  124. data/lib/httpx/plugins/multipart.rb +0 -96
  125. data/sig/plugins/authentication.rbs +0 -13
  126. data/sig/plugins/compression/brotli.rbs +0 -21
  127. data/sig/plugins/compression/deflate.rbs +0 -17
  128. data/sig/plugins/compression/gzip.rbs +0 -29
  129. /data/sig/plugins/{authentication → auth}/digest.rbs +0 -0
  130. /data/sig/plugins/{authentication → auth}/ntlm.rbs +0 -0
  131. /data/sig/plugins/{authentication → auth}/socks5.rbs +0 -0
@@ -1,304 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
- begin
5
- require "idnx"
4
+ module Punycode
5
+ module_function
6
6
 
7
- module Punycode
8
- module_function
7
+ begin
8
+ require "idnx"
9
9
 
10
10
  def encode_hostname(hostname)
11
11
  Idnx.to_punycode(hostname)
12
12
  end
13
- end
14
-
15
- rescue LoadError
16
- # :nocov:
17
- # -*- coding: utf-8 -*-
18
- #--
19
- # punycode.rb - PunyCode encoder for the Domain Name library
20
- #
21
- # Copyright (C) 2011-2017 Akinori MUSHA, All rights reserved.
22
- #
23
- # Ported from puny.c, a part of VeriSign XCode (encode/decode) IDN
24
- # Library.
25
- #
26
- # Copyright (C) 2000-2002 Verisign Inc., All rights reserved.
27
- #
28
- # Redistribution and use in source and binary forms, with or
29
- # without modification, are permitted provided that the following
30
- # conditions are met:
31
- #
32
- # 1) Redistributions of source code must retain the above copyright
33
- # notice, this list of conditions and the following disclaimer.
34
- #
35
- # 2) Redistributions in binary form must reproduce the above copyright
36
- # notice, this list of conditions and the following disclaimer in
37
- # the documentation and/or other materials provided with the
38
- # distribution.
39
- #
40
- # 3) Neither the name of the VeriSign Inc. nor the names of its
41
- # contributors may be used to endorse or promote products derived
42
- # from this software without specific prior written permission.
43
- #
44
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
45
- # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
46
- # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
47
- # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
48
- # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
49
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
50
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
51
- # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
52
- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
54
- # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55
- # POSSIBILITY OF SUCH DAMAGE.
56
- #
57
- # This software is licensed under the BSD open source license. For more
58
- # information visit www.opensource.org.
59
- #
60
- # Authors:
61
- # John Colosi (VeriSign)
62
- # Srikanth Veeramachaneni (VeriSign)
63
- # Nagesh Chigurupati (Verisign)
64
- # Praveen Srinivasan(Verisign)
65
- #++
66
- module Punycode
67
- BASE = 36
68
- TMIN = 1
69
- TMAX = 26
70
- SKEW = 38
71
- DAMP = 700
72
- INITIAL_BIAS = 72
73
- INITIAL_N = 0x80
74
- DELIMITER = "-"
75
-
76
- MAXINT = (1 << 32) - 1
77
-
78
- LOBASE = BASE - TMIN
79
- CUTOFF = LOBASE * TMAX / 2
80
-
81
- RE_NONBASIC = /[^\x00-\x7f]/.freeze
82
-
83
- # Returns the numeric value of a basic code point (for use in
84
- # representing integers) in the range 0 to base-1, or nil if cp
85
- # is does not represent a value.
86
- DECODE_DIGIT = {}.tap do |map|
87
- # ASCII A..Z map to 0..25
88
- # ASCII a..z map to 0..25
89
- (0..25).each { |i| map[65 + i] = map[97 + i] = i }
90
- # ASCII 0..9 map to 26..35
91
- (26..35).each { |i| map[22 + i] = i }
92
- end
93
-
94
- # Returns the basic code point whose value (when used for
95
- # representing integers) is d, which must be in the range 0 to
96
- # BASE-1. The lowercase form is used unless flag is true, in
97
- # which case the uppercase form is used. The behavior is
98
- # undefined if flag is nonzero and digit d has no uppercase
99
- # form.
100
- ENCODE_DIGIT = proc { |d, flag|
101
- (d + 22 + (d < 26 ? 75 : 0) - (flag ? (1 << 5) : 0)).chr
102
- # 0..25 map to ASCII a..z or A..Z
103
- # 26..35 map to ASCII 0..9
104
- }
105
-
106
- DOT = "."
107
- PREFIX = "xn--"
108
-
109
- # Most errors we raise are basically kind of ArgumentError.
110
- class ArgumentError < ::ArgumentError; end
111
- class BufferOverflowError < ArgumentError; end
112
-
113
- module_function
114
-
115
- # Encode a +string+ in Punycode
116
- def encode(string)
117
- input = string.unpack("U*")
118
- output = +""
119
-
120
- # Initialize the state
121
- n = INITIAL_N
122
- delta = 0
123
- bias = INITIAL_BIAS
124
-
125
- # Handle the basic code points
126
- input.each { |cp| output << cp.chr if cp < 0x80 }
127
-
128
- h = b = output.length
129
-
130
- # h is the number of code points that have been handled, b is the
131
- # number of basic code points, and out is the number of characters
132
- # that have been output.
133
-
134
- output << DELIMITER if b > 0
135
-
136
- # Main encoding loop
137
-
138
- while h < input.length
139
- # All non-basic code points < n have been handled already. Find
140
- # the next larger one
141
-
142
- m = MAXINT
143
- input.each do |cp|
144
- m = cp if (n...m) === cp
145
- end
146
-
147
- # Increase delta enough to advance the decoder's <n,i> state to
148
- # <m,0>, but guard against overflow
149
-
150
- delta += (m - n) * (h + 1)
151
- raise BufferOverflowError if delta > MAXINT
152
-
153
- n = m
154
-
155
- input.each do |cp|
156
- # AMC-ACE-Z can use this simplified version instead
157
- if cp < n
158
- delta += 1
159
- raise BufferOverflowError if delta > MAXINT
160
- elsif cp == n
161
- # Represent delta as a generalized variable-length integer
162
- q = delta
163
- k = BASE
164
- loop do
165
- t = k <= bias ? TMIN : k - bias >= TMAX ? TMAX : k - bias
166
- break if q < t
167
-
168
- q, r = (q - t).divmod(BASE - t)
169
- output << ENCODE_DIGIT[t + r, false]
170
- k += BASE
171
- end
172
-
173
- output << ENCODE_DIGIT[q, false]
174
-
175
- # Adapt the bias
176
- delta = h == b ? delta / DAMP : delta >> 1
177
- delta += delta / (h + 1)
178
- bias = 0
179
- while delta > CUTOFF
180
- delta /= LOBASE
181
- bias += BASE
182
- end
183
- bias += (LOBASE + 1) * delta / (delta + SKEW)
184
-
185
- delta = 0
186
- h += 1
187
- end
188
- end
189
-
190
- delta += 1
191
- n += 1
192
- end
193
-
194
- output
195
- end
196
-
197
- # Encode a hostname using IDN/Punycode algorithms
13
+ rescue LoadError
198
14
  def encode_hostname(hostname)
199
- hostname.match(RE_NONBASIC) || (return hostname)
200
-
201
- hostname.split(DOT).map do |name|
202
- if name.match(RE_NONBASIC)
203
- PREFIX + encode(name)
204
- else
205
- name
206
- end
207
- end.join(DOT)
208
- end
209
-
210
- # Decode a +string+ encoded in Punycode
211
- def decode(string)
212
- # Initialize the state
213
- n = INITIAL_N
214
- i = 0
215
- bias = INITIAL_BIAS
216
-
217
- if j = string.rindex(DELIMITER)
218
- b = string[0...j]
219
-
220
- b.match(RE_NONBASIC) &&
221
- raise(ArgumentError, "Illegal character is found in basic part: #{string.inspect}")
222
-
223
- # Handle the basic code points
224
-
225
- output = b.unpack("U*")
226
- u = string[(j + 1)..-1]
227
- else
228
- output = []
229
- u = string
230
- end
231
-
232
- # Main decoding loop: Start just after the last delimiter if any
233
- # basic code points were copied; start at the beginning
234
- # otherwise.
235
-
236
- input = u.unpack("C*")
237
- input_length = input.length
238
- h = 0
239
- out = output.length
240
-
241
- while h < input_length
242
- # Decode a generalized variable-length integer into delta,
243
- # which gets added to i. The overflow checking is easier
244
- # if we increase i as we go, then subtract off its starting
245
- # value at the end to obtain delta.
246
-
247
- oldi = i
248
- w = 1
249
- k = BASE
250
-
251
- loop do
252
- (digit = DECODE_DIGIT[input[h]]) ||
253
- raise(ArgumentError, "Illegal character is found in non-basic part: #{string.inspect}")
254
- h += 1
255
- i += digit * w
256
- raise BufferOverflowError if i > MAXINT
257
-
258
- t = k <= bias ? TMIN : k - bias >= TMAX ? TMAX : k - bias
259
- break if digit < t
260
-
261
- w *= BASE - t
262
- raise BufferOverflowError if w > MAXINT
263
-
264
- k += BASE
265
- (h < input_length) || raise(ArgumentError, "Malformed input given: #{string.inspect}")
266
- end
267
-
268
- # Adapt the bias
269
- delta = oldi == 0 ? i / DAMP : (i - oldi) >> 1
270
- delta += delta / (out + 1)
271
- bias = 0
272
- while delta > CUTOFF
273
- delta /= LOBASE
274
- bias += BASE
275
- end
276
- bias += (LOBASE + 1) * delta / (delta + SKEW)
277
-
278
- # i was supposed to wrap around from out+1 to 0, incrementing
279
- # n each time, so we'll fix that now:
280
-
281
- q, i = i.divmod(out + 1)
282
- n += q
283
- raise BufferOverflowError if n > MAXINT
284
-
285
- # Insert n at position i of the output:
286
-
287
- output[i, 0] = n
288
-
289
- out += 1
290
- i += 1
291
- end
292
- output.pack("U*")
293
- end
15
+ warn "#{hostname} cannot be converted to punycode. Install the " \
16
+ "\"idnx\" gem: https://github.com/HoneyryderChuck/idnx"
294
17
 
295
- # Decode a hostname using IDN/Punycode algorithms
296
- def decode_hostname(hostname)
297
- hostname.gsub(/(\A|#{Regexp.quote(DOT)})#{Regexp.quote(PREFIX)}([^#{Regexp.quote(DOT)}]*)/o) do
298
- Regexp.last_match(1) << decode(Regexp.last_match(2))
299
- end
18
+ hostname
300
19
  end
301
20
  end
302
- # :nocov:
303
21
  end
304
- end
22
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ class Request::Body < SimpleDelegator
5
+ class << self
6
+ def new(_, options)
7
+ return options.body if options.body.is_a?(self)
8
+
9
+ super
10
+ end
11
+ end
12
+
13
+ attr_reader :threshold_size
14
+
15
+ def initialize(headers, options)
16
+ @headers = headers
17
+ @threshold_size = options.body_threshold_size
18
+
19
+ # forego compression in the Range cases
20
+ if @headers.key?("range")
21
+ @headers.delete("accept-encoding")
22
+ else
23
+ @headers["accept-encoding"] ||= options.supported_compression_formats
24
+ end
25
+
26
+ initialize_body(options)
27
+
28
+ return if @body.nil?
29
+
30
+ @headers["content-type"] ||= @body.content_type
31
+ @headers["content-length"] = @body.bytesize unless unbounded_body?
32
+ super(@body)
33
+ end
34
+
35
+ def each(&block)
36
+ return enum_for(__method__) unless block
37
+ return if @body.nil?
38
+
39
+ body = stream(@body)
40
+ if body.respond_to?(:read)
41
+ ::IO.copy_stream(body, ProcIO.new(block))
42
+ elsif body.respond_to?(:each)
43
+ body.each(&block)
44
+ else
45
+ block[body.to_s]
46
+ end
47
+ end
48
+
49
+ def rewind
50
+ return if empty?
51
+
52
+ @body.rewind if @body.respond_to?(:rewind)
53
+ end
54
+
55
+ def empty?
56
+ return true if @body.nil?
57
+ return false if chunked?
58
+
59
+ @body.bytesize.zero?
60
+ end
61
+
62
+ def bytesize
63
+ return 0 if @body.nil?
64
+
65
+ @body.bytesize
66
+ end
67
+
68
+ def stream(body)
69
+ encoded = body
70
+ encoded = Transcoder::Chunker.encode(body.enum_for(:each)) if chunked?
71
+ encoded
72
+ end
73
+
74
+ def unbounded_body?
75
+ return @unbounded_body if defined?(@unbounded_body)
76
+
77
+ @unbounded_body = !@body.nil? && (chunked? || @body.bytesize == Float::INFINITY)
78
+ end
79
+
80
+ def chunked?
81
+ @headers["transfer-encoding"] == "chunked"
82
+ end
83
+
84
+ def chunk!
85
+ @headers.add("transfer-encoding", "chunked")
86
+ end
87
+
88
+ # :nocov:
89
+ def inspect
90
+ "#<HTTPX::Request::Body:#{object_id} " \
91
+ "#{unbounded_body? ? "stream" : "@bytesize=#{bytesize}"}>"
92
+ end
93
+ # :nocov:
94
+
95
+ private
96
+
97
+ def initialize_body(options)
98
+ @body = if options.body
99
+ Transcoder::Body.encode(options.body)
100
+ elsif options.form
101
+ Transcoder::Form.encode(options.form)
102
+ elsif options.json
103
+ Transcoder::JSON.encode(options.json)
104
+ elsif options.xml
105
+ Transcoder::Xml.encode(options.xml)
106
+ end
107
+
108
+ return unless @body
109
+
110
+ return unless options.compress_request_body
111
+
112
+ return unless @headers.key?("content-encoding")
113
+
114
+ @headers.get("content-encoding").each do |encoding|
115
+ @body = self.class.initialize_deflater_body(@body, encoding)
116
+ end
117
+ end
118
+
119
+ class << self
120
+ def initialize_deflater_body(body, encoding)
121
+ case encoding
122
+ when "gzip"
123
+ Transcoder::GZIP.encode(body)
124
+ when "deflate"
125
+ Transcoder::Deflate.encode(body)
126
+ when "identity"
127
+ body
128
+ else
129
+ body
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ class ProcIO
136
+ def initialize(block)
137
+ @block = block
138
+ end
139
+
140
+ def write(data)
141
+ @block.call(data.dup)
142
+ data.bytesize
143
+ end
144
+ end
145
+ end
data/lib/httpx/request.rb CHANGED
@@ -19,10 +19,6 @@ module HTTPX
19
19
  def_delegator :@body, :empty?
20
20
 
21
21
  def initialize(verb, uri, options = {})
22
- if verb.is_a?(Symbol)
23
- warn "DEPRECATION WARNING: Using symbols for `verb` is deprecated, and will not be supported in httpx 1.0. " \
24
- "Use \"#{verb.to_s.upcase}\" instead."
25
- end
26
22
  @verb = verb.to_s.upcase
27
23
  @options = Options.new(options)
28
24
  @uri = Utils.to_uri(uri)
@@ -69,16 +65,6 @@ module HTTPX
69
65
  :w
70
66
  end
71
67
 
72
- if RUBY_VERSION < "2.2"
73
- URIParser = URI::DEFAULT_PARSER
74
-
75
- def initialize_with_escape(verb, uri, options = {})
76
- initialize_without_escape(verb, URIParser.escape(uri.to_s), options)
77
- end
78
- alias_method :initialize_without_escape, :initialize
79
- alias_method :initialize, :initialize_with_escape
80
- end
81
-
82
68
  def merge_headers(h)
83
69
  @headers = @headers.merge(h)
84
70
  end
@@ -153,100 +139,6 @@ module HTTPX
153
139
  end
154
140
  # :nocov:
155
141
 
156
- class Body < SimpleDelegator
157
- class << self
158
- def new(_, options)
159
- return options.body if options.body.is_a?(self)
160
-
161
- super
162
- end
163
- end
164
-
165
- def initialize(headers, options)
166
- @headers = headers
167
- @body = initialize_body(options)
168
- return if @body.nil?
169
-
170
- @headers["content-type"] ||= @body.content_type
171
- @headers["content-length"] = @body.bytesize unless unbounded_body?
172
- super(@body)
173
- end
174
-
175
- def each(&block)
176
- return enum_for(__method__) unless block
177
- return if @body.nil?
178
-
179
- body = stream(@body)
180
- if body.respond_to?(:read)
181
- ::IO.copy_stream(body, ProcIO.new(block))
182
- elsif body.respond_to?(:each)
183
- body.each(&block)
184
- else
185
- block[body.to_s]
186
- end
187
- end
188
-
189
- def rewind
190
- return if empty?
191
-
192
- @body.rewind if @body.respond_to?(:rewind)
193
- end
194
-
195
- def empty?
196
- return true if @body.nil?
197
- return false if chunked?
198
-
199
- @body.bytesize.zero?
200
- end
201
-
202
- def bytesize
203
- return 0 if @body.nil?
204
-
205
- @body.bytesize
206
- end
207
-
208
- def stream(body)
209
- encoded = body
210
- encoded = Transcoder::Chunker.encode(body.enum_for(:each)) if chunked?
211
- encoded
212
- end
213
-
214
- def unbounded_body?
215
- return @unbounded_body if defined?(@unbounded_body)
216
-
217
- @unbounded_body = !@body.nil? && (chunked? || @body.bytesize == Float::INFINITY)
218
- end
219
-
220
- def chunked?
221
- @headers["transfer-encoding"] == "chunked"
222
- end
223
-
224
- def chunk!
225
- @headers.add("transfer-encoding", "chunked")
226
- end
227
-
228
- # :nocov:
229
- def inspect
230
- "#<HTTPX::Request::Body:#{object_id} " \
231
- "#{unbounded_body? ? "stream" : "@bytesize=#{bytesize}"}>"
232
- end
233
- # :nocov:
234
-
235
- private
236
-
237
- def initialize_body(options)
238
- if options.body
239
- Transcoder::Body.encode(options.body)
240
- elsif options.form
241
- Transcoder::Form.encode(options.form)
242
- elsif options.json
243
- Transcoder::JSON.encode(options.json)
244
- elsif options.xml
245
- Transcoder::Xml.encode(options.xml)
246
- end
247
- end
248
- end
249
-
250
142
  def transition(nextstate)
251
143
  case nextstate
252
144
  when :idle
@@ -284,16 +176,7 @@ module HTTPX
284
176
  def expects?
285
177
  @headers["expect"] == "100-continue" && @informational_status == 100 && !@response
286
178
  end
287
-
288
- class ProcIO
289
- def initialize(block)
290
- @block = block
291
- end
292
-
293
- def write(data)
294
- @block.call(data.dup)
295
- data.bytesize
296
- end
297
- end
298
179
  end
299
180
  end
181
+
182
+ require_relative "request/body"
@@ -4,12 +4,12 @@ require "resolv"
4
4
  require "uri"
5
5
  require "cgi"
6
6
  require "forwardable"
7
+ require "httpx/base64"
7
8
 
8
9
  module HTTPX
9
10
  class Resolver::HTTPS < Resolver::Resolver
10
11
  extend Forwardable
11
12
  using URIExtensions
12
- using StringExtensions
13
13
 
14
14
  module DNSExtensions
15
15
  refine Resolv::DNS do
@@ -8,20 +8,12 @@ module HTTPX
8
8
  extend Forwardable
9
9
  using URIExtensions
10
10
 
11
- DEFAULTS = if RUBY_VERSION < "2.2"
12
- {
13
- **Resolv::DNS::Config.default_config_hash,
14
- packet_size: 512,
15
- timeouts: Resolver::RESOLVE_TIMEOUT,
16
- }
17
- else
18
- {
19
- nameserver: nil,
20
- **Resolv::DNS::Config.default_config_hash,
21
- packet_size: 512,
22
- timeouts: Resolver::RESOLVE_TIMEOUT,
23
- }
24
- end.freeze
11
+ DEFAULTS = {
12
+ nameserver: nil,
13
+ **Resolv::DNS::Config.default_config_hash,
14
+ packet_size: 512,
15
+ timeouts: Resolver::RESOLVE_TIMEOUT,
16
+ }.freeze
25
17
 
26
18
  DNS_PORT = 53
27
19
 
@@ -95,7 +95,7 @@ module HTTPX
95
95
  end
96
96
 
97
97
  def resolve_error(hostname, ex = nil)
98
- return ex if ex.is_a?(ResolveError)
98
+ return ex if ex.is_a?(ResolveError) || ex.is_a?(ResolveTimeoutError)
99
99
 
100
100
  message = ex ? ex.message : "Can't resolve #{hostname}"
101
101
  error = ResolveError.new(message)
@@ -92,6 +92,12 @@ module HTTPX
92
92
  resolve
93
93
  end
94
94
 
95
+ def raise_timeout_error(interval)
96
+ error = HTTPX::ResolveTimeoutError.new(interval, "timed out while waiting on select")
97
+ error.set_backtrace(caller)
98
+ on_error(error)
99
+ end
100
+
95
101
  private
96
102
 
97
103
  def transition(nextstate)
@@ -164,6 +170,7 @@ module HTTPX
164
170
  Thread.current.report_on_exception = false
165
171
  begin
166
172
  addrs = if resolve_timeout
173
+
167
174
  Timeout.timeout(resolve_timeout) do
168
175
  __addrinfo_resolve(hostname, scheme)
169
176
  end
@@ -182,16 +189,11 @@ module HTTPX
182
189
  @pipe_write.putc(DONE) unless @pipe_write.closed?
183
190
  end
184
191
  end
185
- rescue Timeout::Error => e
186
- ex = ResolveTimeoutError.new(resolve_timeout, e.message)
187
- ex.set_backtrace(ex.backtrace)
188
- @pipe_mutex.synchronize do
189
- families.each do |family|
190
- @ips.unshift([family, connection, ex])
191
- @pipe_write.putc(ERROR) unless @pipe_write.closed?
192
- end
193
- end
194
192
  rescue StandardError => e
193
+ if e.is_a?(Timeout::Error)
194
+ e = ResolveTimeoutError.new(resolve_timeout, e.message)
195
+ e.set_backtrace(e.backtrace)
196
+ end
195
197
  @pipe_mutex.synchronize do
196
198
  families.each do |family|
197
199
  @ips.unshift([family, connection, e])