httpx 0.14.0 → 0.14.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: abbeaccc55115244f08e7b39aaad174a34dd2e7aeb10b32cdc0563fbefe1b953
4
- data.tar.gz: a39fc4e5644b21c1265840011e969c36904756573584cba0f805d568a549ec94
3
+ metadata.gz: 16f2f2bc0c8dfff4c7a92bc573f25e717a703f06fa8f336bde41bd60ad86ad87
4
+ data.tar.gz: 313f1fe9ec2c3d5a04f838c36d6ceee6982c60e3b4d6646644428f0c5c6d1d74
5
5
  SHA512:
6
- metadata.gz: 82fa475dcd9ef05ebe90f0b3c742c17c33185410a70eb5af730fce393681b7f9f346decf78349614f77b76257550c0e3056e61f3b5d6cd5efdba0149eff235f6
7
- data.tar.gz: 64ceb596415b440c99c9df31569fa0ee2f7c94e51787d5e0d84141f1ade0be92e23e2d7011a361c1366b43c4f159525599367009bd4021c358537f11c4605cac
6
+ metadata.gz: 6780278b2b12254fe0f1a884a78d7e102e965d2d5f93b7431a2239e5b2d5e8c25e6e122715af89b03e786ba752b265d53d94d1f3a66cac7fe2a26299ff25491d
7
+ data.tar.gz: e85a43e840647f60a721481e112c8b8672f3f478d4bacdae6337c52beca5e3a198e2e9f0206592ecb111dfd0b5be33addf2f2e930255750ed89f145631f8d66c
@@ -0,0 +1,7 @@
1
+ # 0.14.1
2
+
3
+
4
+ ## Bugfixes
5
+
6
+ * fixed: HTTP/2-specific headers were being reused on insecure redirects, thereby creating an invalid request (#128);
7
+ * fixed: multipart request parts weren't using explicity set `:content_type`, instead using file mime type or "text/plain";
@@ -0,0 +1,6 @@
1
+ # 0.14.2
2
+
3
+
4
+ ## Bugfixes
5
+
6
+ * fixed: multipart request parts weren't using explicity set `:filename`.
@@ -0,0 +1,5 @@
1
+ # 0.14.3
2
+
3
+ ## Bugfixes
4
+
5
+ * fixed: HTTP/1 "connection: close" header was "leaking" into subsequent redirect follow, including HTTP/2 requests which would fail due to the invalid header.
@@ -0,0 +1,5 @@
1
+ # 0.14.4
2
+
3
+ ## Bugfixes
4
+
5
+ * The HTTP/1 handler was miscalculating the last request for a given connection, and potentially freezing it.
@@ -0,0 +1,11 @@
1
+ # 0.14.5
2
+
3
+ ## Bugfixes
4
+
5
+ * After a connection had been initiated, sending multiple concurrent requests (ex: `open_httpx.request(req1, req2, req3)`) could freeze; this happened when the first request would fill the write buffer (like a file upload request), and the subsequent requests would never be buffered afterwards; this was fixed by making pending requests flushing a part of a connection's consumption loop.
6
+ * Fixing v0.14.1's fixed bug again; The HTTP/1 "Connection: close" header was not being set in the last possible request on a connection, due to ann off-by-one error on connection bookkeeping;
7
+ * HTTP/1 connections didn't respect a server-set max nunmber of requests after a reconnect; Fixed by making this accounting part of the reset process;
8
+
9
+ ## Chore
10
+
11
+ * Added regression test suite, which reproduce reported bugs before the fix (backported all 0.14.x releases here)
@@ -360,6 +360,8 @@ module HTTPX
360
360
  write_drained = false
361
361
  end unless interests == :r
362
362
 
363
+ send_pending if @state == :open
364
+
363
365
  # return if socket is drained
364
366
  next unless (interests != :r || read_drained) &&
365
367
  (interests != :w || write_drained)
@@ -40,6 +40,7 @@ module HTTPX
40
40
  def reset
41
41
  @max_requests = @options.max_requests || MAX_REQUESTS
42
42
  @parser.reset!
43
+ @handshake_completed = false
43
44
  end
44
45
 
45
46
  def close
@@ -80,7 +81,6 @@ module HTTPX
80
81
  break if idx >= concurrent_requests_limit
81
82
  next if request.state == :done
82
83
 
83
- request.headers["connection"] ||= request.options.persistent || idx < requests_limit - 1 ? "keep-alive" : "close"
84
84
  handle(request)
85
85
  end
86
86
  end
@@ -254,12 +254,24 @@ module HTTPX
254
254
  end
255
255
 
256
256
  def set_protocol_headers(request)
257
- request.headers["host"] ||= request.authority
258
- request.headers["connection"] ||= request.options.persistent ? "keep-alive" : "close"
259
257
  if !request.headers.key?("content-length") &&
260
258
  request.body.bytesize == Float::INFINITY
261
259
  request.chunk!
262
260
  end
261
+
262
+ requests_limit = [@max_requests, @requests.size].min
263
+
264
+ connection = if request != @requests[requests_limit - 1] &&
265
+ request.options.persistent && @max_requests != 1
266
+ "keep-alive"
267
+ else
268
+ "close"
269
+ end
270
+
271
+ {
272
+ "host" => (request.headers["host"] || request.authority),
273
+ "connection" => connection,
274
+ }
263
275
  end
264
276
 
265
277
  def headline_uri(request)
@@ -282,8 +294,8 @@ module HTTPX
282
294
  def join_headers(request)
283
295
  @buffer << "#{request.verb.to_s.upcase} #{headline_uri(request)} HTTP/#{@version.join(".")}" << CRLF
284
296
  log(color: :yellow) { "<- HEADLINE: #{@buffer.to_s.chomp.inspect}" }
285
- set_protocol_headers(request)
286
- join_headers2(request.headers)
297
+ extra_headers = set_protocol_headers(request)
298
+ join_headers2(request.headers.each(extra_headers))
287
299
  log { "<- " }
288
300
  @buffer << CRLF
289
301
  end
@@ -192,18 +192,20 @@ module HTTPX
192
192
  end
193
193
 
194
194
  def set_protocol_headers(request)
195
- request.headers[":scheme"] = request.scheme
196
- request.headers[":method"] = request.verb.to_s.upcase
197
- request.headers[":path"] = headline_uri(request)
198
- request.headers[":authority"] = request.authority
195
+ {
196
+ ":scheme" => request.scheme,
197
+ ":method" => request.verb.to_s.upcase,
198
+ ":path" => headline_uri(request),
199
+ ":authority" => request.authority,
200
+ }
199
201
  end
200
202
 
201
203
  def join_headers(stream, request)
202
- set_protocol_headers(request)
204
+ extra_headers = set_protocol_headers(request)
203
205
  log(level: 1, color: :yellow) do
204
- request.headers.each.map { |k, v| "#{stream.id}: -> HEADER: #{k}: #{v}" }.join("\n")
206
+ request.headers.merge(extra_headers).each.map { |k, v| "#{stream.id}: -> HEADER: #{k}: #{v}" }.join("\n")
205
207
  end
206
- stream.headers(request.headers.each, end_stream: request.empty?)
208
+ stream.headers(request.headers.each(extra_headers), end_stream: request.empty?)
207
209
  end
208
210
 
209
211
  def join_trailers(stream, request)
data/lib/httpx/headers.rb CHANGED
@@ -103,12 +103,16 @@ module HTTPX
103
103
  # returns the enumerable headers store in pairs of header field + the values in
104
104
  # the comma-separated string format
105
105
  #
106
- def each
107
- return enum_for(__method__) { @headers.size } unless block_given?
106
+ def each(extra_headers = nil)
107
+ return enum_for(__method__, extra_headers) { @headers.size } unless block_given?
108
108
 
109
109
  @headers.each do |field, value|
110
110
  yield(field, value.join(", ")) unless value.empty?
111
111
  end
112
+
113
+ extra_headers.each do |field, value|
114
+ yield(field, value) unless value.empty?
115
+ end if extra_headers
112
116
  end
113
117
 
114
118
  def ==(other)
data/lib/httpx/idna.rb ADDED
@@ -0,0 +1,15 @@
1
+ module HTTPX
2
+ module IDNA
3
+ module_function
4
+
5
+ begin
6
+ require "idn"
7
+
8
+ def convert(non_ascii_hostname); end
9
+ rescue LoadError
10
+ def convert(non_ascii_hostname)
11
+ DomainName.new(non_ascii_hostname).hostname
12
+ end
13
+ end
14
+ end
15
+ end
@@ -26,7 +26,7 @@ module HTTPX
26
26
  content_type ||= MimeTypeDetector.call(value, filename) || "application/octet-stream"
27
27
  [value, content_type, filename]
28
28
  else
29
- [StringIO.new(value.to_s), "text/plain"]
29
+ [StringIO.new(value.to_s), content_type || "text/plain", filename]
30
30
  end
31
31
  end
32
32
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ module Plugins
5
+ #
6
+ # https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#ntlm-authentication
7
+ #
8
+ module NTLMAuthentication
9
+ NTLMParams = Struct.new(:user, :domain, :password)
10
+
11
+ class << self
12
+ def load_dependencies(_klass)
13
+ require "base64"
14
+ require "ntlm"
15
+ end
16
+
17
+ def configure(klass)
18
+ klass.plugin(:authentication)
19
+ end
20
+
21
+ def extra_options(options)
22
+ Class.new(options.class) do
23
+ def_option(:ntlm, <<-OUT)
24
+ raise Error, ":ntlm must be a #{NTLMParams}" unless value.is_a?(#{NTLMParams})
25
+
26
+ value
27
+ OUT
28
+ end.new(options).merge(max_concurrent_requests: 1)
29
+ end
30
+ end
31
+
32
+ module InstanceMethods
33
+ def ntlm_authentication(user, password, domain = nil)
34
+ with(ntlm: NTLMParams.new(user, domain, password))
35
+ end
36
+
37
+ alias_method :ntlm_auth, :ntlm_authentication
38
+
39
+ def request(*args, **options)
40
+ requests = build_requests(*args, options)
41
+ request = requests.first
42
+ ntlm = request.options.ntlm
43
+
44
+ return super(*requests, **options) unless ntlm
45
+
46
+ request.headers["authorization"] = "NTLM #{NTLM.negotiate(domain: ntlm.domain).to_base64}"
47
+ probe_response = wrap { send_requests(*request, options).first }
48
+
49
+ return probe_response unless probe_response.status == 401 && probe_response.headers.key?("www-authenticate") &&
50
+ (challenge = probe_response.headers["www-authenticate"][/NTLM (.*)/, 1])
51
+
52
+ challenge = Base64.decode64(challenge)
53
+ ntlm_challenge = NTLM.authenticate(challenge, ntlm.user, ntlm.domain, ntlm.password).to_base64
54
+
55
+ request.transition(:idle)
56
+
57
+ request.headers["authorization"] = "NTLM #{ntlm_challenge}"
58
+ super(request, **options)
59
+ end
60
+ end
61
+ end
62
+ register_plugin :ntlm_authentication, NTLMAuthentication
63
+ end
64
+ end
@@ -82,11 +82,12 @@ module HTTPX
82
82
  end
83
83
 
84
84
  def set_protocol_headers(request)
85
- super
85
+ extra_headers = super
86
+
86
87
  proxy_params = @options.proxy
87
- request.headers["proxy-authorization"] = "Basic #{proxy_params.token_authentication}" if proxy_params.authenticated?
88
- request.headers["proxy-connection"] = request.headers["connection"]
89
- request.headers.delete("connection")
88
+ extra_headers["proxy-authorization"] = "Basic #{proxy_params.token_authentication}" if proxy_params.authenticated?
89
+ extra_headers["proxy-connection"] = extra_headers.delete("connection") if extra_headers.key?("connection")
90
+ extra_headers
90
91
  end
91
92
  end
92
93
 
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.14.0"
4
+ VERSION = "0.14.5"
5
5
  end
@@ -52,7 +52,7 @@ module HTTPX
52
52
 
53
53
  def disable_pipelining: () -> void
54
54
 
55
- def set_protocol_headers: (Request) -> void
55
+ def set_protocol_headers: (Request) -> _Each[headers_key, String]
56
56
 
57
57
  def headline_uri: (Request) -> String
58
58
 
@@ -62,7 +62,7 @@ module HTTPX
62
62
 
63
63
  def join_trailers: (Request request) -> void
64
64
 
65
- def join_headers2: (Headers headers) -> void
65
+ def join_headers2: (_Each[headers_key, String] headers) -> void
66
66
 
67
67
  def join_body: (Request request) -> void
68
68
 
@@ -43,7 +43,7 @@ module HTTPX
43
43
 
44
44
  def headline_uri: (Request) -> String
45
45
 
46
- def set_protocol_headers: (Request) -> void
46
+ def set_protocol_headers: (Request) -> _Each[headers_key, String]
47
47
 
48
48
  def handle: (Request request, HTTP2Next::Stream stream) -> void
49
49
 
data/sig/headers.rbs CHANGED
@@ -14,8 +14,8 @@ module HTTPX
14
14
  def add: (headers_key field, string value) -> void
15
15
  def delete: (headers_key field) -> void
16
16
 
17
- def each: () { (headers_key, String) -> void } -> void
18
- | () -> Enumerable[[headers_key, String], void]
17
+ def each: (?_Each[headers_key, String]? extra_headers) { (headers_key, String) -> void } -> void
18
+ | (?_Each[headers_key, String]? extra_headers) -> Enumerable[[headers_key, String], void]
19
19
 
20
20
  def get: (headers_key field) -> Array[String]
21
21
  def key?: (headers_key downcased_key) -> bool
@@ -33,7 +33,7 @@ module HTTPX
33
33
  end
34
34
 
35
35
  module Part
36
- def self?.call: (multipart_nested_value) -> ([_Reader, String, String?] | [_Reader, String])
36
+ def self?.call: (multipart_nested_value) -> ([_Reader, String, String?])
37
37
  end
38
38
 
39
39
  module MimeTypeDetector
@@ -0,0 +1,27 @@
1
+ module HTTPX
2
+ module Plugins
3
+ module NTLMAuthentication
4
+
5
+ interface _NTLMOptions
6
+ def ntlm: () -> NTLMParams?
7
+ def ntlm=: (NTLMParams) -> NTLMParams
8
+ end
9
+
10
+ def self.extra_options: (Options) -> (Options & _NTLMOptions)
11
+
12
+ def self.load_dependencies: (*untyped) -> void
13
+
14
+ module InstanceMethods
15
+ def ntlm_authentication: (string user, string password, ?string? domain) -> instance
16
+ end
17
+
18
+ class NTLMParams
19
+ attr_reader user: String
20
+ attr_reader password: String
21
+ attr_reader domain: String?
22
+ end
23
+ end
24
+
25
+ type sessionNTLMAuthentication = Plugins::sessionAuthentication & Plugins::NTLMAuthentication::InstanceMethods
26
+ end
27
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.14.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-05-22 00:00:00.000000000 Z
11
+ date: 2021-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http-2-next
@@ -47,10 +47,13 @@ extra_rdoc_files:
47
47
  - LICENSE.txt
48
48
  - README.md
49
49
  - doc/release_notes/0_0_1.md
50
+ - doc/release_notes/0_14_5.md
50
51
  - doc/release_notes/0_1_0.md
51
52
  - doc/release_notes/0_0_5.md
53
+ - doc/release_notes/0_14_1.md
52
54
  - doc/release_notes/0_0_4.md
53
55
  - doc/release_notes/0_14_0.md
56
+ - doc/release_notes/0_14_4.md
54
57
  - doc/release_notes/0_6_5.md
55
58
  - doc/release_notes/0_13_0.md
56
59
  - doc/release_notes/0_6_1.md
@@ -80,10 +83,12 @@ extra_rdoc_files:
80
83
  - doc/release_notes/0_11_1.md
81
84
  - doc/release_notes/0_8_0.md
82
85
  - doc/release_notes/0_3_0.md
86
+ - doc/release_notes/0_14_3.md
83
87
  - doc/release_notes/0_2_1.md
84
88
  - doc/release_notes/0_0_3.md
85
89
  - doc/release_notes/0_0_2.md
86
90
  - doc/release_notes/0_3_1.md
91
+ - doc/release_notes/0_14_2.md
87
92
  - doc/release_notes/0_2_0.md
88
93
  files:
89
94
  - LICENSE.txt
@@ -105,6 +110,11 @@ files:
105
110
  - doc/release_notes/0_13_1.md
106
111
  - doc/release_notes/0_13_2.md
107
112
  - doc/release_notes/0_14_0.md
113
+ - doc/release_notes/0_14_1.md
114
+ - doc/release_notes/0_14_2.md
115
+ - doc/release_notes/0_14_3.md
116
+ - doc/release_notes/0_14_4.md
117
+ - doc/release_notes/0_14_5.md
108
118
  - doc/release_notes/0_1_0.md
109
119
  - doc/release_notes/0_2_0.md
110
120
  - doc/release_notes/0_2_1.md
@@ -142,6 +152,7 @@ files:
142
152
  - lib/httpx/errors.rb
143
153
  - lib/httpx/extensions.rb
144
154
  - lib/httpx/headers.rb
155
+ - lib/httpx/idna.rb
145
156
  - lib/httpx/io.rb
146
157
  - lib/httpx/io/ssl.rb
147
158
  - lib/httpx/io/tcp.rb
@@ -178,6 +189,7 @@ files:
178
189
  - lib/httpx/plugins/multipart/encoder.rb
179
190
  - lib/httpx/plugins/multipart/mime_type_detector.rb
180
191
  - lib/httpx/plugins/multipart/part.rb
192
+ - lib/httpx/plugins/ntlm_authentication.rb
181
193
  - lib/httpx/plugins/persistent.rb
182
194
  - lib/httpx/plugins/proxy.rb
183
195
  - lib/httpx/plugins/proxy/http.rb
@@ -237,6 +249,7 @@ files:
237
249
  - sig/plugins/follow_redirects.rbs
238
250
  - sig/plugins/h2c.rbs
239
251
  - sig/plugins/multipart.rbs
252
+ - sig/plugins/ntlm_authentication.rbs
240
253
  - sig/plugins/persistent.rbs
241
254
  - sig/plugins/proxy.rbs
242
255
  - sig/plugins/proxy/http.rbs
@@ -272,7 +285,7 @@ metadata:
272
285
  changelog_uri: https://honeyryderchuck.gitlab.io/httpx/#release-notes
273
286
  documentation_uri: https://honeyryderchuck.gitlab.io/httpx/rdoc/
274
287
  source_code_uri: https://gitlab.com/honeyryderchuck/httpx
275
- post_install_message:
288
+ post_install_message:
276
289
  rdoc_options: []
277
290
  require_paths:
278
291
  - lib
@@ -287,8 +300,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
287
300
  - !ruby/object:Gem::Version
288
301
  version: '0'
289
302
  requirements: []
290
- rubygems_version: 3.1.6
291
- signing_key:
303
+ rubygems_version: 3.0.3
304
+ signing_key:
292
305
  specification_version: 4
293
306
  summary: HTTPX, to the future, and beyond
294
307
  test_files: []