httpx 0.14.0 → 0.14.5

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.
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: []