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 +4 -4
- data/doc/release_notes/0_14_1.md +7 -0
- data/doc/release_notes/0_14_2.md +6 -0
- data/doc/release_notes/0_14_3.md +5 -0
- data/doc/release_notes/0_14_4.md +5 -0
- data/doc/release_notes/0_14_5.md +11 -0
- data/lib/httpx/connection.rb +2 -0
- data/lib/httpx/connection/http1.rb +17 -5
- data/lib/httpx/connection/http2.rb +9 -7
- data/lib/httpx/headers.rb +6 -2
- data/lib/httpx/idna.rb +15 -0
- data/lib/httpx/plugins/multipart/part.rb +1 -1
- data/lib/httpx/plugins/ntlm_authentication.rb +64 -0
- data/lib/httpx/plugins/proxy/http.rb +5 -4
- data/lib/httpx/version.rb +1 -1
- data/sig/connection/http1.rbs +2 -2
- data/sig/connection/http2.rbs +1 -1
- data/sig/headers.rbs +2 -2
- data/sig/plugins/multipart.rbs +1 -1
- data/sig/plugins/ntlm_authentication.rbs +27 -0
- metadata +19 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16f2f2bc0c8dfff4c7a92bc573f25e717a703f06fa8f336bde41bd60ad86ad87
|
4
|
+
data.tar.gz: 313f1fe9ec2c3d5a04f838c36d6ceee6982c60e3b4d6646644428f0c5c6d1d74
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,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)
|
data/lib/httpx/connection.rb
CHANGED
@@ -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
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
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
@@ -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
|
-
|
88
|
-
|
89
|
-
|
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
data/sig/connection/http1.rbs
CHANGED
@@ -52,7 +52,7 @@ module HTTPX
|
|
52
52
|
|
53
53
|
def disable_pipelining: () -> void
|
54
54
|
|
55
|
-
def set_protocol_headers: (Request) ->
|
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: (
|
65
|
+
def join_headers2: (_Each[headers_key, String] headers) -> void
|
66
66
|
|
67
67
|
def join_body: (Request request) -> void
|
68
68
|
|
data/sig/connection/http2.rbs
CHANGED
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
|
data/sig/plugins/multipart.rbs
CHANGED
@@ -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.
|
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-
|
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.
|
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: []
|