httpx 0.18.1 → 0.18.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc0ed6728252132961087b7747743f0011f2f8100eb9b242080b7ac29ce68752
4
- data.tar.gz: 68c3c8f592d2e7599b7a5dcca4e9f73e7d61aba743bacb17d4c276c404203f5e
3
+ metadata.gz: 843e16ae32c900167850fe3a864446af2cd6b6a9d3ca6368f64b999964a1a5b2
4
+ data.tar.gz: 533464195c08ab7e0ba2e5aa7871fdf8b59e59643122ca48ce5e7cf8a6ebb351
5
5
  SHA512:
6
- metadata.gz: 162b4b96df5b3b76bccdbe5940ed09aac4dea1d4b019321b07f859912d5d9fb770080d69198c70e4fd69a745723e250bcfce34e76baa83fdf3352f63d0b14620
7
- data.tar.gz: 63099247e157ddd0b1f01bdbd459a51500b5bb7ac0a624a93c09958efbd10ec2c79027c5bb932ccacfa3335a8f9d0c7691b835ac30eabbe1ed6f7ced3a47421d
6
+ metadata.gz: 6e170cf6a47bce0a1eeeea25c53870615958f77e2fe9eb9b4176783b860bc26c8d45712e0ad758ba2481bd2712a21bb14d10a32fb5f17871a9421413edf162ac
7
+ data.tar.gz: ae5a0bc77a54cf66528dfd89c7127b5ce64730be6fc0fe8be6d79966dfa36e2e04b348f39e1e91d3b457e34c35f8b3a33e18bc656f7823874ffbaedc72e3b8ad
data/README.md CHANGED
@@ -45,7 +45,7 @@ response = HTTPX.get("https://nghttp2.org")
45
45
  puts response.status #=> 200
46
46
  body = response.body
47
47
  puts body #=> #<HTTPX::Response ...
48
- ```
48
+ ```
49
49
 
50
50
  You can also send as many requests as you want simultaneously:
51
51
 
@@ -79,7 +79,7 @@ In Ruby, HTTP client implementations are a known cheap commodity. Why this one?
79
79
 
80
80
  ### Concurrency
81
81
 
82
- This library supports HTTP/2 seamlessly (which means, if the request is secure, and the server support ALPN negotiation AND HTTP/2, the request will be made through HTTP/2). If you pass multiple URIs, and they can utilize the same connection, they will run concurrently in it.
82
+ This library supports HTTP/2 seamlessly (which means, if the request is secure, and the server support ALPN negotiation AND HTTP/2, the request will be made through HTTP/2). If you pass multiple URIs, and they can utilize the same connection, they will run concurrently in it.
83
83
 
84
84
  However if the server supports HTTP/1.1, it will try to use HTTP pipelining, falling back to 1 request at a time if the server doesn't support it (if the server support Keep-Alive connections, it will reuse the same connection).
85
85
 
@@ -137,7 +137,8 @@ In order to use HTTP/2 under JRuby, [check this link](https://gitlab.com/honeyry
137
137
 
138
138
  ### Known bugs
139
139
 
140
- Doesn't work with ruby 2.4.0 for Windows (see [#36](https://gitlab.com/honeyryderchuck/httpx/issues/36)).
140
+ * Doesn't work with ruby 2.4.0 for Windows (see [#36](https://gitlab.com/honeyryderchuck/httpx/issues/36)).
141
+ * Using `total_timeout` along with the `:persistent` plugin [does not work as you might expect](https://gitlab.com/honeyryderchuck/httpx/-/wikis/Timeouts#total_timeout).
141
142
 
142
143
  ## Contributing
143
144
 
@@ -0,0 +1,10 @@
1
+ # 0.18.2
2
+
3
+ ## Bugfixes
4
+
5
+ * A bug was reported and fixed, whereby a persistent connection with a `:total_timeout` set was triggering the timeout and leaving the process looping indefinitely.
6
+
7
+
8
+ ## Chore
9
+
10
+ The quirk of using the `:persistent` plugin with `:total_timeout` has been documented: https://gitlab.com/honeyryderchuck/httpx/-/wikis/Timeouts#total_timeout.
@@ -0,0 +1,7 @@
1
+ # 0.18.3
2
+
3
+ ## Bugfixes
4
+
5
+ * request bodies eager-loaded from enumerables yield duped partial chunks.
6
+
7
+ An error was observed while looking at webmock integration, where requests formed via the multipart plugin were returning an empty string as body. The issue was caused by an optimization on multipart encoder, which reuses the same buffer when reading chunks. Unfortunately, these cannot be yielded the same way via IO.copy_stream, as the same (cleared) buffer will be used to generate the eager-loaded body chunks.
@@ -0,0 +1,14 @@
1
+ # 0.18.4
2
+
3
+ ## Improvements
4
+
5
+ * faraday adapter: added support for `#on_data` callback in order to support [faraday streaming](https://lostisland.github.io/faraday/usage/streaming).
6
+
7
+ * multipart plugin: removed support for file mime type detection using `mime-types`. The reasoning behind it was that `mime-types` uses the filename, which is a very inaccurate detection strategy (ex: an mp4 video will be identified as `application/mp4`, instead of the correct `video/mp4`).
8
+ * multipart plugin: supported for file mime type detection using `marcel` and `filemagic` was added. Both use the magic header bytes, which is a more accurate strategy for file type detection.
9
+
10
+ ## Bugfixes
11
+
12
+ * webmock adapter has been reimplemented to work with `httpx` plugins (such as the `:retries` plugin). Some other fixes were applied to make it work better under `vcr` (a common `webmock` extension).
13
+
14
+ * fixed the URI-related bug which was making requests stall under ruby 3.1 (still not officially testing against it).
@@ -0,0 +1,10 @@
1
+ # 0.18.5
2
+
3
+ ## Improvements
4
+
5
+ * ruby 3.1 is now officially supported.
6
+ * when user sets a `Host` header for an HTTP/2 request, this will be used in the `:authority` HTTP/2 pseudo-header, instead of silently ignored (mimicking what "curl" does).
7
+
8
+ ## Bugfixes
9
+
10
+ * fixed "throw outside of catch block" error happening when pipelining requests on an HTTP/1 connnection and resulting in a timeout.
@@ -21,6 +21,17 @@ module Faraday
21
21
  end
22
22
  # :nocov:
23
23
 
24
+ unless Faraday::RequestOptions.method_defined?(:stream_response?)
25
+ module RequestOptionsExtensions
26
+ refine Faraday::RequestOptions do
27
+ def stream_response?
28
+ false
29
+ end
30
+ end
31
+ end
32
+ using RequestOptionsExtensions
33
+ end
34
+
24
35
  module RequestMixin
25
36
  using ::HTTPX::HashExtensions
26
37
 
@@ -64,6 +75,27 @@ module Faraday
64
75
 
65
76
  include RequestMixin
66
77
 
78
+ module OnDataPlugin
79
+ module RequestMethods
80
+ attr_writer :response_on_data
81
+
82
+ def response=(response)
83
+ super
84
+ response.body.on_data = @response_on_data
85
+ end
86
+ end
87
+
88
+ module ResponseBodyMethods
89
+ attr_writer :on_data
90
+
91
+ def write(chunk)
92
+ return super unless @on_data
93
+
94
+ @on_data.call(chunk, chunk.bytesize)
95
+ end
96
+ end
97
+ end
98
+
67
99
  class Session < ::HTTPX::Session
68
100
  plugin(:compression)
69
101
  plugin(:persistent)
@@ -137,15 +169,21 @@ module Faraday
137
169
  end
138
170
 
139
171
  def run
140
- requests = @handlers.map { |handler| build_request(handler.env) }
141
172
  env = @handlers.last.env
142
173
 
143
- proxy_options = { uri: env.request.proxy }
144
-
145
174
  session = @session.with(options_from_env(env))
146
- session = session.plugin(:proxy).with(proxy: proxy_options) if env.request.proxy
175
+ session = session.plugin(:proxy).with(proxy: { uri: env.request.proxy }) if env.request.proxy
176
+ session = session.plugin(OnDataPlugin) if env.request.stream_response?
177
+
178
+ requests = @handlers.map { |handler| session.build_request(*build_request(handler.env)) }
179
+
180
+ if env.request.stream_response?
181
+ requests.each do |request|
182
+ request.response_on_data = env.request.on_data
183
+ end
184
+ end
147
185
 
148
- responses = session.request(requests)
186
+ responses = session.request(*requests)
149
187
  Array(responses).each_with_index do |response, index|
150
188
  handler = @handlers[index]
151
189
  handler.on_response.call(response)
@@ -179,11 +217,15 @@ module Faraday
179
217
  return handler
180
218
  end
181
219
 
182
- meth, uri, request_options = build_request(env)
183
-
184
220
  session = @session.with(options_from_env(env))
185
- session = session.plugin(:proxy).with(proxy: proxy_options) if env.request.proxy
186
- response = session.__send__(meth, uri, **request_options)
221
+ session = session.plugin(:proxy).with(proxy: { uri: env.request.proxy }) if env.request.proxy
222
+ session = session.plugin(OnDataPlugin) if env.request.stream_response?
223
+
224
+ request = session.build_request(*build_request(env))
225
+
226
+ request.response_on_data = env.request.on_data if env.request.stream_response?
227
+
228
+ response = session.request(request)
187
229
  response.raise_for_status unless response.is_a?(::HTTPX::Response)
188
230
  save_response(env, response.status, response.body.to_s, response.headers, response.reason) do |response_headers|
189
231
  response_headers.merge!(response.headers)
@@ -16,56 +16,8 @@ module WebMock
16
16
  # Requests are "hijacked" at the session, before they're distributed to a connection.
17
17
  #
18
18
  module Plugin
19
- module InstanceMethods
20
- private
21
-
22
- def send_requests(*requests)
23
- request_signatures = requests.map do |request|
24
- request_signature = _build_webmock_request_signature(request)
25
- WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
26
- request_signature
27
- end
28
-
29
- responses = request_signatures.map do |request_signature|
30
- WebMock::StubRegistry.instance.response_for_request(request_signature)
31
- end
32
-
33
- real_requests = {}
34
-
35
- requests.each_with_index.each_with_object([request_signatures, responses]) do |(request, idx), (sig_reqs, mock_responses)|
36
- if (webmock_response = mock_responses[idx])
37
- mock_responses[idx] = _build_from_webmock_response(request, webmock_response)
38
- WebMock::CallbackRegistry.invoke_callbacks({ lib: :httpx }, sig_reqs[idx], webmock_response)
39
- log { "mocking #{request.uri} with #{mock_responses[idx].inspect}" }
40
- elsif WebMock.net_connect_allowed?(sig_reqs[idx].uri)
41
- log { "performing #{request.uri}" }
42
- real_requests[request] = idx
43
- else
44
- raise WebMock::NetConnectNotAllowedError, sig_reqs[idx]
45
- end
46
- end
47
-
48
- unless real_requests.empty?
49
- reqs = real_requests.keys
50
- reqs.zip(super(*reqs)).each do |req, res|
51
- idx = real_requests[req]
52
-
53
- if WebMock::CallbackRegistry.any_callbacks?
54
- webmock_response = _build_webmock_response(req, res)
55
- WebMock::CallbackRegistry.invoke_callbacks(
56
- { lib: :httpx, real_request: true }, request_signatures[idx],
57
- webmock_response
58
- )
59
- end
60
-
61
- responses[idx] = res
62
- end
63
- end
64
-
65
- responses
66
- end
67
-
68
- def _build_webmock_request_signature(request)
19
+ class << self
20
+ def build_webmock_request_signature(request)
69
21
  uri = WebMock::Util::URI.heuristic_parse(request.uri)
70
22
  uri.path = uri.normalized_path.gsub("[^:]//", "/")
71
23
 
@@ -77,7 +29,7 @@ module WebMock
77
29
  )
78
30
  end
79
31
 
80
- def _build_webmock_response(_request, response)
32
+ def build_webmock_response(_request, response)
81
33
  webmock_response = WebMock::Response.new
82
34
  webmock_response.status = [response.status, HTTP_REASONS[response.status]]
83
35
  webmock_response.body = response.body.to_s
@@ -85,10 +37,10 @@ module WebMock
85
37
  webmock_response
86
38
  end
87
39
 
88
- def _build_from_webmock_response(request, webmock_response)
89
- return _build_error_response(request, HTTPX::TimeoutError.new(1, "Timed out")) if webmock_response.should_timeout
40
+ def build_from_webmock_response(request, webmock_response)
41
+ return build_error_response(request, HTTPX::TimeoutError.new(1, "Timed out")) if webmock_response.should_timeout
90
42
 
91
- return _build_error_response(request, webmock_response.exception) if webmock_response.exception
43
+ return build_error_response(request, webmock_response.exception) if webmock_response.exception
92
44
 
93
45
  response = request.options.response_class.new(request,
94
46
  webmock_response.status[0],
@@ -98,10 +50,70 @@ module WebMock
98
50
  response
99
51
  end
100
52
 
101
- def _build_error_response(request, exception)
53
+ def build_error_response(request, exception)
102
54
  HTTPX::ErrorResponse.new(request, exception, request.options)
103
55
  end
104
56
  end
57
+
58
+ module InstanceMethods
59
+ def build_connection(*)
60
+ connection = super
61
+ connection.once(:unmock_connection) do
62
+ pool.__send__(:resolve_connection, connection)
63
+ pool.__send__(:unregister_connection, connection) unless connection.addresses
64
+ end
65
+ connection
66
+ end
67
+ end
68
+
69
+ module ConnectionMethods
70
+ def initialize(*)
71
+ super
72
+ @mocked = true
73
+ end
74
+
75
+ def open?
76
+ return true if @mocked
77
+
78
+ super
79
+ end
80
+
81
+ def interests
82
+ return if @mocked
83
+
84
+ super
85
+ end
86
+
87
+ def send(request)
88
+ request_signature = Plugin.build_webmock_request_signature(request)
89
+ WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
90
+
91
+ if (mock_response = WebMock::StubRegistry.instance.response_for_request(request_signature))
92
+ response = Plugin.build_from_webmock_response(request, mock_response)
93
+ WebMock::CallbackRegistry.invoke_callbacks({ lib: :httpx }, request_signature, mock_response)
94
+ log { "mocking #{request.uri} with #{mock_response.inspect}" }
95
+ request.response = response
96
+ request.emit(:response, response)
97
+ elsif WebMock.net_connect_allowed?(request_signature.uri)
98
+ if WebMock::CallbackRegistry.any_callbacks?
99
+ request.on(:response) do |resp|
100
+ unless resp.is_a?(HTTPX::ErrorResponse)
101
+ webmock_response = Plugin.build_webmock_response(request, resp)
102
+ WebMock::CallbackRegistry.invoke_callbacks(
103
+ { lib: :httpx, real_request: true }, request_signature,
104
+ webmock_response
105
+ )
106
+ end
107
+ end
108
+ end
109
+ @mocked = false
110
+ emit(:unmock_connection, self)
111
+ super
112
+ else
113
+ raise WebMock::NetConnectNotAllowedError, request_signature
114
+ end
115
+ end
116
+ end
105
117
  end
106
118
 
107
119
  class HttpxAdapter < HttpLibAdapter
@@ -109,12 +121,12 @@ module WebMock
109
121
 
110
122
  class << self
111
123
  def enable!
112
- @original_session = ::HTTPX::Session
124
+ @original_session = HTTPX::Session
113
125
 
114
- webmock_session = ::HTTPX.plugin(Plugin)
126
+ webmock_session = HTTPX.plugin(Plugin)
115
127
 
116
- ::HTTPX.send(:remove_const, :Session)
117
- ::HTTPX.send(:const_set, :Session, webmock_session.class)
128
+ HTTPX.send(:remove_const, :Session)
129
+ HTTPX.send(:const_set, :Session, webmock_session.class)
118
130
  end
119
131
 
120
132
  def disable!
data/lib/httpx/altsvc.rb CHANGED
@@ -70,7 +70,7 @@ module HTTPX
70
70
 
71
71
  scanner = StringScanner.new(altsvc)
72
72
  until scanner.eos?
73
- alt_origin = scanner.scan(/[^=]+=("[^"]+"|[^;,]+)/)
73
+ alt_service = scanner.scan(/[^=]+=("[^"]+"|[^;,]+)/)
74
74
 
75
75
  alt_params = []
76
76
  loop do
@@ -80,29 +80,45 @@ module HTTPX
80
80
  break if scanner.eos? || scanner.scan(/ *, */)
81
81
  end
82
82
  alt_params = Hash[alt_params.map { |field| field.split("=") }]
83
- yield(parse_altsvc_origin(alt_origin), alt_params)
83
+
84
+ alt_proto, alt_authority = alt_service.split("=")
85
+ alt_origin = parse_altsvc_origin(alt_proto, alt_authority)
86
+ return unless alt_origin
87
+
88
+ yield(alt_origin, alt_params.merge("proto" => alt_proto))
89
+ end
90
+ end
91
+
92
+ def parse_altsvc_scheme(alt_proto)
93
+ case alt_proto
94
+ when "h2c"
95
+ "http"
96
+ when "h2"
97
+ "https"
84
98
  end
85
99
  end
86
100
 
87
101
  # :nocov:
88
102
  if RUBY_VERSION < "2.2"
89
- def parse_altsvc_origin(alt_origin)
90
- alt_proto, alt_origin = alt_origin.split("=")
103
+ def parse_altsvc_origin(alt_proto, alt_origin)
104
+ alt_scheme = parse_altsvc_scheme(alt_proto) or return
105
+
91
106
  alt_origin = alt_origin[1..-2] if alt_origin.start_with?("\"") && alt_origin.end_with?("\"")
92
107
  if alt_origin.start_with?(":")
93
- alt_origin = "#{alt_proto}://dummy#{alt_origin}"
108
+ alt_origin = "#{alt_scheme}://dummy#{alt_origin}"
94
109
  uri = URI.parse(alt_origin)
95
110
  uri.host = nil
96
111
  uri
97
112
  else
98
- URI.parse("#{alt_proto}://#{alt_origin}")
113
+ URI.parse("#{alt_scheme}://#{alt_origin}")
99
114
  end
100
115
  end
101
116
  else
102
- def parse_altsvc_origin(alt_origin)
103
- alt_proto, alt_origin = alt_origin.split("=")
117
+ def parse_altsvc_origin(alt_proto, alt_origin)
118
+ alt_scheme = parse_altsvc_scheme(alt_proto) or return
104
119
  alt_origin = alt_origin[1..-2] if alt_origin.start_with?("\"") && alt_origin.end_with?("\"")
105
- URI.parse("#{alt_proto}://#{alt_origin}")
120
+
121
+ URI.parse("#{alt_scheme}://#{alt_origin}")
106
122
  end
107
123
  end
108
124
  # :nocov:
@@ -184,7 +184,7 @@ module HTTPX
184
184
  end
185
185
 
186
186
  if @pipelining
187
- disable
187
+ catch(:called) { disable }
188
188
  else
189
189
  @requests.each do |request|
190
190
  emit(:error, request, ex)
@@ -220,6 +220,12 @@ module HTTPX
220
220
 
221
221
  def join_headers(stream, request)
222
222
  extra_headers = set_protocol_headers(request)
223
+
224
+ if request.headers.key?("host")
225
+ log { "forbidden \"host\" header found (#{request.headers["host"]}), will use it as authority..." }
226
+ extra_headers[":authority"] = request.headers["host"]
227
+ end
228
+
223
229
  log(level: 1, color: :yellow) do
224
230
  request.headers.merge(extra_headers).each.map { |k, v| "#{stream.id}: -> HEADER: #{k}: #{v}" }.join("\n")
225
231
  end
data/lib/httpx/io/udp.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "socket"
4
3
  require "ipaddr"
5
4
 
6
5
  module HTTPX
@@ -8,11 +8,19 @@ module HTTPX
8
8
  DEFAULT_MIMETYPE = "application/octet-stream"
9
9
 
10
10
  # inspired by https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/determine_mime_type.rb
11
- if defined?(MIME::Types)
11
+ if defined?(FileMagic)
12
+ def call(file, _)
13
+ return nil if file.eof? # FileMagic returns "application/x-empty" for empty files
14
+
15
+ FileMagic.open(FileMagic::MAGIC_MIME_TYPE) do |filemagic|
16
+ filemagic.buffer(file.read(MAGIC_NUMBER))
17
+ end
18
+ end
19
+ elsif defined?(Marcel)
20
+ def call(file, filename)
21
+ return nil if file.eof? # marcel returns "application/octet-stream" for empty files
12
22
 
13
- def call(_file, filename)
14
- mime = MIME::Types.of(filename).first
15
- mime.content_type if mime
23
+ Marcel::MimeType.for(file, name: filename)
16
24
  end
17
25
 
18
26
  elsif defined?(MimeMagic)
@@ -138,10 +138,20 @@ module HTTPX
138
138
  error = response.error
139
139
  case error
140
140
  when NativeResolveError
141
+ return false unless @_proxy_uris && !@_proxy_uris.empty?
142
+
143
+ proxy_uri = URI(@_proxy_uris.first)
144
+
145
+ origin = error.connection.origin
146
+
141
147
  # failed resolving proxy domain
142
- error.connection.origin.to_s == @_proxy_uris.first
148
+ origin.host == proxy_uri.host && origin.port == proxy_uri.port
143
149
  when ResolveError
144
- error.message.end_with?(@_proxy_uris.first)
150
+ return false unless @_proxy_uris && !@_proxy_uris.empty?
151
+
152
+ proxy_uri = URI(@_proxy_uris.first)
153
+
154
+ error.message.end_with?(proxy_uri.to_s)
145
155
  when *PROXY_ERRORS
146
156
  # timeout errors connecting to proxy
147
157
  true
@@ -160,7 +170,9 @@ module HTTPX
160
170
 
161
171
  # redefining the connection origin as the proxy's URI,
162
172
  # as this will be used as the tcp peer ip.
163
- @origin = URI(@options.proxy.uri.origin)
173
+ proxy_uri = URI(@options.proxy.uri)
174
+ @origin.host = proxy_uri.host
175
+ @origin.port = proxy_uri.port
164
176
  end
165
177
 
166
178
  def match?(uri, options)
data/lib/httpx/request.rb CHANGED
@@ -285,7 +285,7 @@ module HTTPX
285
285
  end
286
286
 
287
287
  def write(data)
288
- @block.call(data)
288
+ @block.call(data.dup)
289
289
  data.bytesize
290
290
  end
291
291
  end
@@ -117,6 +117,13 @@ class HTTPX::Selector
117
117
  end
118
118
 
119
119
  def select(interval, &block)
120
+ # do not cause an infinite loop here.
121
+ #
122
+ # this may happen if timeout calculation actually triggered an error which causes
123
+ # the connections to be reaped (such as the total timeout error) before #select
124
+ # gets called.
125
+ return if interval.nil? && @selectables.empty?
126
+
120
127
  return select_one(interval, &block) if @selectables.size == 1
121
128
 
122
129
  select_many(interval, &block)
data/lib/httpx/session.rb CHANGED
@@ -163,7 +163,7 @@ module HTTPX
163
163
  case uri.scheme
164
164
  when "http"
165
165
  "tcp"
166
- when "https", "h2"
166
+ when "https"
167
167
  "ssl"
168
168
  else
169
169
  raise UnsupportedSchemeError, "#{uri}: #{uri.scheme}: unsupported URI scheme"
data/lib/httpx/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
- VERSION = "0.18.1"
4
+ VERSION = "0.18.5"
5
5
  end
metadata CHANGED
@@ -1,24 +1,24 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.1
4
+ version: 0.18.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-23 00:00:00.000000000 Z
11
+ date: 2022-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2-next
15
- prerelease: false
16
15
  requirement: !ruby/object:Gem::Requirement
17
16
  requirements:
18
17
  - - ">="
19
18
  - !ruby/object:Gem::Version
20
19
  version: 0.4.1
21
20
  type: :runtime
21
+ prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
@@ -33,59 +33,63 @@ extra_rdoc_files:
33
33
  - LICENSE.txt
34
34
  - README.md
35
35
  - doc/release_notes/0_0_1.md
36
- - doc/release_notes/0_15_4.md
37
- - doc/release_notes/0_14_5.md
38
- - doc/release_notes/0_18_1.md
39
- - doc/release_notes/0_1_0.md
40
- - doc/release_notes/0_0_5.md
41
- - doc/release_notes/0_15_0.md
42
- - doc/release_notes/0_14_1.md
36
+ - doc/release_notes/0_0_2.md
37
+ - doc/release_notes/0_0_3.md
43
38
  - doc/release_notes/0_0_4.md
44
- - doc/release_notes/0_15_1.md
45
- - doc/release_notes/0_14_0.md
46
- - doc/release_notes/0_14_4.md
47
- - doc/release_notes/0_18_0.md
48
- - doc/release_notes/0_6_5.md
49
- - doc/release_notes/0_13_0.md
50
- - doc/release_notes/0_6_1.md
51
- - doc/release_notes/0_11_2.md
52
- - doc/release_notes/0_7_0.md
53
- - doc/release_notes/0_6_0.md
39
+ - doc/release_notes/0_0_5.md
40
+ - doc/release_notes/0_10_0.md
41
+ - doc/release_notes/0_10_1.md
54
42
  - doc/release_notes/0_10_2.md
43
+ - doc/release_notes/0_11_0.md
44
+ - doc/release_notes/0_11_1.md
45
+ - doc/release_notes/0_11_2.md
55
46
  - doc/release_notes/0_11_3.md
56
- - doc/release_notes/0_8_2.md
57
- - doc/release_notes/0_6_4.md
58
- - doc/release_notes/0_13_1.md
59
47
  - doc/release_notes/0_12_0.md
60
- - doc/release_notes/0_9_0.md
61
- - doc/release_notes/0_6_3.md
62
- - doc/release_notes/0_10_1.md
63
- - doc/release_notes/0_11_0.md
64
- - doc/release_notes/0_8_1.md
65
- - doc/release_notes/0_5_0.md
66
- - doc/release_notes/0_6_7.md
48
+ - doc/release_notes/0_13_0.md
49
+ - doc/release_notes/0_13_1.md
67
50
  - doc/release_notes/0_13_2.md
68
- - doc/release_notes/0_4_1.md
69
- - doc/release_notes/0_5_1.md
70
- - doc/release_notes/0_6_6.md
71
- - doc/release_notes/0_4_0.md
72
- - doc/release_notes/0_6_2.md
73
- - doc/release_notes/0_10_0.md
74
- - doc/release_notes/0_11_1.md
75
- - doc/release_notes/0_8_0.md
76
- - doc/release_notes/0_3_0.md
77
- - doc/release_notes/0_15_2.md
51
+ - doc/release_notes/0_14_0.md
52
+ - doc/release_notes/0_14_1.md
53
+ - doc/release_notes/0_14_2.md
78
54
  - doc/release_notes/0_14_3.md
79
- - doc/release_notes/0_2_1.md
80
- - doc/release_notes/0_0_3.md
55
+ - doc/release_notes/0_14_4.md
56
+ - doc/release_notes/0_14_5.md
57
+ - doc/release_notes/0_15_0.md
58
+ - doc/release_notes/0_15_1.md
59
+ - doc/release_notes/0_15_2.md
60
+ - doc/release_notes/0_15_3.md
61
+ - doc/release_notes/0_15_4.md
62
+ - doc/release_notes/0_16_0.md
81
63
  - doc/release_notes/0_16_1.md
82
64
  - doc/release_notes/0_17_0.md
83
- - doc/release_notes/0_0_2.md
84
- - doc/release_notes/0_16_0.md
85
- - doc/release_notes/0_3_1.md
86
- - doc/release_notes/0_15_3.md
87
- - doc/release_notes/0_14_2.md
65
+ - doc/release_notes/0_18_0.md
66
+ - doc/release_notes/0_18_1.md
67
+ - doc/release_notes/0_18_2.md
68
+ - doc/release_notes/0_18_3.md
69
+ - doc/release_notes/0_18_4.md
70
+ - doc/release_notes/0_18_5.md
71
+ - doc/release_notes/0_1_0.md
88
72
  - doc/release_notes/0_2_0.md
73
+ - doc/release_notes/0_2_1.md
74
+ - doc/release_notes/0_3_0.md
75
+ - doc/release_notes/0_3_1.md
76
+ - doc/release_notes/0_4_0.md
77
+ - doc/release_notes/0_4_1.md
78
+ - doc/release_notes/0_5_0.md
79
+ - doc/release_notes/0_5_1.md
80
+ - doc/release_notes/0_6_0.md
81
+ - doc/release_notes/0_6_1.md
82
+ - doc/release_notes/0_6_2.md
83
+ - doc/release_notes/0_6_3.md
84
+ - doc/release_notes/0_6_4.md
85
+ - doc/release_notes/0_6_5.md
86
+ - doc/release_notes/0_6_6.md
87
+ - doc/release_notes/0_6_7.md
88
+ - doc/release_notes/0_7_0.md
89
+ - doc/release_notes/0_8_0.md
90
+ - doc/release_notes/0_8_1.md
91
+ - doc/release_notes/0_8_2.md
92
+ - doc/release_notes/0_9_0.md
89
93
  files:
90
94
  - LICENSE.txt
91
95
  - README.md
@@ -121,6 +125,10 @@ files:
121
125
  - doc/release_notes/0_17_0.md
122
126
  - doc/release_notes/0_18_0.md
123
127
  - doc/release_notes/0_18_1.md
128
+ - doc/release_notes/0_18_2.md
129
+ - doc/release_notes/0_18_3.md
130
+ - doc/release_notes/0_18_4.md
131
+ - doc/release_notes/0_18_5.md
124
132
  - doc/release_notes/0_1_0.md
125
133
  - doc/release_notes/0_2_0.md
126
134
  - doc/release_notes/0_2_1.md
@@ -303,7 +311,7 @@ metadata:
303
311
  source_code_uri: https://gitlab.com/honeyryderchuck/httpx
304
312
  homepage_uri: https://honeyryderchuck.gitlab.io/httpx/
305
313
  rubygems_mfa_required: 'true'
306
- post_install_message:
314
+ post_install_message:
307
315
  rdoc_options: []
308
316
  require_paths:
309
317
  - lib
@@ -318,8 +326,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
318
326
  - !ruby/object:Gem::Version
319
327
  version: '0'
320
328
  requirements: []
321
- rubygems_version: 3.1.6
322
- signing_key:
329
+ rubygems_version: 3.2.32
330
+ signing_key:
323
331
  specification_version: 4
324
332
  summary: HTTPX, to the future, and beyond
325
333
  test_files: []