httpx 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/doc/release_notes/0_13_0.md +58 -0
  3. data/lib/httpx/chainable.rb +2 -2
  4. data/lib/httpx/connection.rb +17 -13
  5. data/lib/httpx/connection/http1.rb +4 -2
  6. data/lib/httpx/connection/http2.rb +1 -1
  7. data/lib/httpx/io/ssl.rb +30 -17
  8. data/lib/httpx/io/tcp.rb +45 -26
  9. data/lib/httpx/io/unix.rb +27 -12
  10. data/lib/httpx/options.rb +11 -23
  11. data/lib/httpx/plugins/compression.rb +20 -8
  12. data/lib/httpx/plugins/compression/brotli.rb +8 -6
  13. data/lib/httpx/plugins/compression/deflate.rb +2 -2
  14. data/lib/httpx/plugins/compression/gzip.rb +2 -2
  15. data/lib/httpx/plugins/digest_authentication.rb +1 -1
  16. data/lib/httpx/plugins/follow_redirects.rb +1 -1
  17. data/lib/httpx/plugins/h2c.rb +43 -58
  18. data/lib/httpx/plugins/internal_telemetry.rb +1 -1
  19. data/lib/httpx/plugins/retries.rb +1 -1
  20. data/lib/httpx/plugins/stream.rb +3 -1
  21. data/lib/httpx/plugins/upgrade.rb +83 -0
  22. data/lib/httpx/plugins/upgrade/h2.rb +54 -0
  23. data/lib/httpx/pool.rb +14 -5
  24. data/lib/httpx/response.rb +5 -5
  25. data/lib/httpx/version.rb +1 -1
  26. data/sig/chainable.rbs +2 -1
  27. data/sig/connection/http1.rbs +1 -0
  28. data/sig/options.rbs +7 -20
  29. data/sig/plugins/aws_sigv4.rbs +0 -1
  30. data/sig/plugins/compression.rbs +5 -3
  31. data/sig/plugins/compression/brotli.rbs +1 -1
  32. data/sig/plugins/compression/deflate.rbs +1 -1
  33. data/sig/plugins/compression/gzip.rbs +1 -1
  34. data/sig/plugins/cookies.rbs +0 -1
  35. data/sig/plugins/digest_authentication.rbs +0 -1
  36. data/sig/plugins/expect.rbs +0 -2
  37. data/sig/plugins/follow_redirects.rbs +0 -2
  38. data/sig/plugins/h2c.rbs +5 -10
  39. data/sig/plugins/persistent.rbs +0 -1
  40. data/sig/plugins/proxy.rbs +0 -1
  41. data/sig/plugins/retries.rbs +0 -4
  42. data/sig/plugins/upgrade.rbs +23 -0
  43. data/sig/response.rbs +3 -1
  44. metadata +7 -2
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ module Plugins
5
+ #
6
+ # This plugin adds support for upgrading an HTTP/1.1 connection to HTTP/2
7
+ # via an Upgrade: h2 response declaration
8
+ #
9
+ # https://gitlab.com/honeyryderchuck/httpx/wikis/Upgrade#h2
10
+ #
11
+ module H2
12
+ class << self
13
+ def configure(klass)
14
+ klass.default_options.upgrade_handlers.register "h2", self
15
+ end
16
+
17
+ def call(connection, _request, _response)
18
+ connection.upgrade_to_h2
19
+ end
20
+ end
21
+
22
+ module ConnectionMethods
23
+ using URIExtensions
24
+
25
+ def upgrade_to_h2
26
+ prev_parser = @parser
27
+
28
+ if prev_parser
29
+ prev_parser.reset
30
+ @inflight -= prev_parser.requests.size
31
+ end
32
+
33
+ @parser = Connection::HTTP2.new(@write_buffer, @options)
34
+ set_parser_callbacks(@parser)
35
+ @upgrade_protocol = :h2
36
+
37
+ # what's happening here:
38
+ # a deviation from the state machine is done to perform the actions when a
39
+ # connection is closed, without transitioning, so the connection is kept in the pool.
40
+ # the state is reset to initial, so that the socket reconnect works out of the box,
41
+ # while the parser is already here.
42
+ purge_after_closed
43
+ transition(:idle)
44
+
45
+ prev_parser.requests.each do |req|
46
+ req.transition(:idle)
47
+ send(req)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ register_plugin(:"upgrade/h2", H2)
53
+ end
54
+ end
data/lib/httpx/pool.rb CHANGED
@@ -64,11 +64,6 @@ module HTTPX
64
64
  connection.on(:open) do
65
65
  @connected_connections += 1
66
66
  end
67
- connection.on(:unreachable) do
68
- resolver = find_resolver_for(connection)
69
- resolver.uncache(connection) if resolver
70
- resolve_connection(connection)
71
- end
72
67
  end
73
68
 
74
69
  # opens a connection to the IP reachable through +uri+.
@@ -85,6 +80,20 @@ module HTTPX
85
80
 
86
81
  def resolve_connection(connection)
87
82
  @connections << connection unless @connections.include?(connection)
83
+
84
+ if connection.addresses || connection.state == :open
85
+ #
86
+ # there are two cases in which we want to activate initialization of
87
+ # connection immediately:
88
+ #
89
+ # 1. when the connection already has addresses, i.e. it doesn't need to
90
+ # resolve a name (not the same as name being an IP, yet)
91
+ # 2. when the connection is initialized with an external already open IO.
92
+ #
93
+ on_resolver_connection(connection)
94
+ return
95
+ end
96
+
88
97
  resolver = find_resolver_for(connection)
89
98
  resolver << connection
90
99
  return if resolver.empty?
@@ -27,8 +27,7 @@ module HTTPX
27
27
  @version = version
28
28
  @status = Integer(status)
29
29
  @headers = @options.headers_class.new(headers)
30
- @body = @options.response_body_class.new(self, threshold_size: @options.body_threshold_size,
31
- window_size: @options.window_size)
30
+ @body = @options.response_body_class.new(self, @options)
32
31
  end
33
32
 
34
33
  def merge_headers(h)
@@ -83,11 +82,12 @@ module HTTPX
83
82
  end
84
83
 
85
84
  class Body
86
- def initialize(response, threshold_size:, window_size: 1 << 14)
85
+ def initialize(response, options)
87
86
  @response = response
88
87
  @headers = response.headers
89
- @threshold_size = threshold_size
90
- @window_size = window_size
88
+ @options = options
89
+ @threshold_size = options.body_threshold_size
90
+ @window_size = options.window_size
91
91
  @encoding = response.content_type.charset || Encoding::BINARY
92
92
  @length = 0
93
93
  @buffer = nil
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.12.0"
4
+ VERSION = "0.13.0"
5
5
  end
data/sig/chainable.rbs CHANGED
@@ -18,7 +18,8 @@ module HTTPX
18
18
  | (:cookies) -> Plugins::sessionCookies
19
19
  | (:expect) -> Session
20
20
  | (:follow_redirects) -> Plugins::sessionFollowRedirects
21
- | (:h2c) -> Plugins::sessionH2C
21
+ | (:upgrade) -> Session
22
+ | (:h2c) -> Session
22
23
  | (:multipart) -> Session
23
24
  | (:persistent) -> Plugins::sessionPersistent
24
25
  | (:proxy) -> Plugins::sessionProxy
@@ -4,6 +4,7 @@ module HTTPX
4
4
  include Loggable
5
5
 
6
6
  attr_reader pending: Array[Request]
7
+ attr_reader requests: Array[Request]
7
8
 
8
9
  @options: Options
9
10
  @max_concurrent_requests: Integer
data/sig/options.rbs CHANGED
@@ -11,62 +11,54 @@ module HTTPX
11
11
  # headers
12
12
  attr_reader headers: Headers?
13
13
  def headers=: (headers) -> void
14
- def with_headers: (headers) -> instance
15
14
 
16
15
  # timeout
17
16
  attr_reader timeout: Timeout?
18
17
  def timeout=: (Hash[Symbol, untyped] | Timeout) -> void
19
- def with_timeout: (Hash[Symbol, untyped] | Timeout) -> instance
20
18
 
21
19
  # max_concurrent_requests
22
20
  attr_reader max_concurrent_requests: Integer?
23
21
  def max_concurrent_requests=: (Integer) -> void
24
- def with_max_concurrent_requests: (Integer) -> instance
25
22
 
26
23
  # max_requests
27
24
  attr_reader max_requests: Integer?
28
25
  def max_requests=: (Integer) -> void
29
- def with_max_requests: (Integer) -> instance
30
26
 
31
27
  # window_size
32
28
  attr_reader window_size: int?
33
29
  def window_size=: (int) -> void
34
- def with_window_size: (int) -> instance
35
30
 
36
31
  # body_threshold_size
37
32
  attr_reader body_threshold_size: int?
38
33
  def body_threshold_size=: (int) -> void
39
- def with_body_threshold_size: (int) -> instance
40
34
 
41
35
  # transport
42
36
  attr_reader transport: _ToS?
43
37
  def transport=: (_ToS) -> void
44
- def with_transport: (_ToS) -> instance
45
38
 
46
39
  # transport_options
47
40
  attr_reader transport_options: Hash[untyped, untyped]?
48
41
  def transport_options=: (Hash[untyped, untyped]) -> void
49
- def with_transport_options: (Hash[untyped, untyped]) -> instance
42
+
43
+ # addresses
44
+ attr_reader addresses: _ToAry[untyped]?
45
+ def addresses=: (_ToAry[untyped]) -> void
50
46
 
51
47
  # params
52
48
  attr_reader params: Transcoder::urlencoded_input?
53
49
  def params=: (Transcoder::urlencoded_input) -> void
54
- def with_params: (Transcoder::urlencoded_input) -> instance
55
50
 
56
51
  # form
57
52
  attr_reader form: Transcoder::urlencoded_input?
58
53
  def form=: (Transcoder::urlencoded_input) -> void
59
- def with_form: (Transcoder::urlencoded_input) -> instance
60
54
 
61
55
  # json
62
56
  attr_reader json: _ToJson?
63
57
  def json=: (_ToJson) -> void
64
- def with_json: (_ToJson) -> instance
65
58
 
66
59
  # body
67
60
  attr_reader body: bodyIO?
68
61
  def body=: (bodyIO) -> void
69
- def with_body: (bodyIO) -> instance
70
62
 
71
63
  # ssl
72
64
 
@@ -79,32 +71,27 @@ module HTTPX
79
71
  # request_class
80
72
  attr_reader request_class: singleton(Request)
81
73
  def request_class=: (singleton(Request)) -> void
82
- def with_request_class: (singleton(Request)) -> instance
83
74
 
84
75
  # io
85
- attr_reader io: _ToIO?
86
- def io=: (_ToIO) -> void
87
- def with_io: (_ToIO) -> instance
76
+ type io_option = _ToIO | Hash[String, _ToIO]
77
+ attr_reader io: io_option?
78
+ def io=: (io_option) -> void
88
79
 
89
80
  # fallback_protocol
90
81
  attr_reader fallback_protocol: String?
91
82
  def fallback_protocol=: (String) -> void
92
- def with_fallback_protocol: (String) -> instance
93
83
 
94
84
  # debug
95
85
  attr_reader debug: _IOLogger?
96
86
  def debug=: (_IOLogger) -> void
97
- def with_debug: (_IOLogger) -> instance
98
87
 
99
88
  # debug_level
100
89
  attr_reader debug_level: Integer?
101
90
  def debug_level=: (Integer) -> void
102
- def with_debug_level: (Integer) -> instance
103
91
 
104
92
  # persistent
105
93
  attr_reader persistent: bool?
106
94
  def persistent=: (bool) -> void
107
- def with_persistent: (bool) -> instance
108
95
 
109
96
  def ==: (untyped other) -> bool
110
97
  def merge: (_ToHash other) -> instance
@@ -43,7 +43,6 @@ module HTTPX
43
43
  interface _SigV4Options
44
44
  def sigv4_signer: () -> Signer?
45
45
  def sigv4_signer=: (Signer) -> Signer
46
- def with_sigv4_signer: (Signer) -> instance
47
46
  end
48
47
 
49
48
  def self.extra_options: (Options) -> (Options & _SigV4Options)
@@ -1,7 +1,7 @@
1
1
  module HTTPX
2
2
  module Plugins
3
3
  module Compression
4
- extend Registry[Symbol, Class]
4
+ type encodings_registry = Registry[Symbol, Class]
5
5
 
6
6
  type deflatable = _Reader | _ToS
7
7
 
@@ -16,12 +16,14 @@ module HTTPX
16
16
  def initialize: (Numeric bytesize) -> untyped
17
17
  end
18
18
 
19
- def self.load_dependencies: (singleton(Session)) -> void
19
+ def self.configure: (singleton(Session)) -> void
20
20
 
21
21
  interface _CompressionOptions
22
22
  def compression_threshold_size: () -> _Integer?
23
23
  def compression_threshold_size=: (int) -> int
24
- def with_compression_threshold_size: (int) -> instance
24
+
25
+ def encodings: () -> encodings_registry?
26
+ def encodings=: (encodings_registry) -> encodings_registry
25
27
  end
26
28
 
27
29
  def self.extra_options: (Options) -> (Options & _CompressionOptions)
@@ -3,7 +3,7 @@ module HTTPX
3
3
  module Compression
4
4
  module Brotli
5
5
  def self.load_dependencies: (singleton(Session)) -> void
6
- def self.configure: (*untyped) -> void
6
+ def self.configure: (singleton(Session)) -> void
7
7
 
8
8
  def self?.deflater: () -> _Deflater
9
9
  def self?.decoder: (Numeric bytesize) -> Inflater
@@ -3,7 +3,7 @@ module HTTPX
3
3
  module Compression
4
4
  module Deflate
5
5
  def self.load_dependencies: (singleton(Session)) -> void
6
- def self.configure: (*untyped) -> void
6
+ def self.configure: (singleton(Session)) -> void
7
7
 
8
8
  def self?.deflater: () -> _Deflater
9
9
  def self?.inflater: (Numeric bytesize) -> GZIP::Inflater
@@ -3,7 +3,7 @@ module HTTPX
3
3
  module Compression
4
4
  module GZIP
5
5
  def self.load_dependencies: (singleton(Session)) -> void
6
- def self.configure: (*untyped) -> void
6
+ def self.configure: (singleton(Session)) -> void
7
7
 
8
8
  def self?.deflater: () -> _Deflater
9
9
  def self?.inflater: (Numeric bytesize) -> Inflater
@@ -6,7 +6,6 @@ module HTTPX
6
6
  interface _CookieOptions
7
7
  def cookies: () -> Jar?
8
8
  def cookies=: (jar) -> Jar
9
- def with_cookies: (jar) -> instance
10
9
  end
11
10
 
12
11
  def self.extra_options: (Options) -> (Options & _CookieOptions)
@@ -6,7 +6,6 @@ module HTTPX
6
6
  interface _DigestOptions
7
7
  def digest: () -> Digest?
8
8
  def digest=: (Digest) -> Digest
9
- def with_digest: (Digest) -> instance
10
9
  end
11
10
 
12
11
  def self.extra_options: (Options) -> (Options & _DigestOptions)
@@ -6,11 +6,9 @@ module HTTPX
6
6
  interface _ExpectOptions
7
7
  def expect_timeout: () -> Integer?
8
8
  def expect_timeout=: (int) -> Integer
9
- def with_expect_timeout: (int) -> instance
10
9
 
11
10
  def expect_threshold_size: () -> Integer?
12
11
  def expect_threshold_size=: (int) -> Integer
13
- def with_expect_threshold_size: (int) -> instance
14
12
  end
15
13
 
16
14
  def self.extra_options: (Options) -> (Options & _ExpectOptions)
@@ -9,11 +9,9 @@ module HTTPX
9
9
  interface _FollowRedirectsOptions
10
10
  def max_redirects: () -> Integer?
11
11
  def max_redirects=: (int) -> Integer
12
- def with_max_redirects: (int) -> instance
13
12
 
14
13
  def follow_insecure_redirects: () -> bool?
15
14
  def follow_insecure_redirects=: (bool) -> bool
16
- def with_follow_insecure_redirects: (bool) -> instance
17
15
  end
18
16
 
19
17
  def self.extra_options: (Options) -> (Options & _FollowRedirectsOptions)
data/sig/plugins/h2c.rbs CHANGED
@@ -1,23 +1,18 @@
1
1
  module HTTPX
2
2
  module Plugins
3
3
  module H2C
4
- def self.load_dependencies: (singleton(Session)) -> void
5
-
6
- module InstanceMethods
7
- VALID_H2C_METHODS: Array[Symbol]
8
-
9
- private
4
+ VALID_H2C_VERBS: Array[Symbol]
10
5
 
11
- def valid_h2c_upgrade_request: (Request) -> bool
12
- def valid_h2c_upgrade?: (Request, Response, Options) -> bool
13
- end
6
+ def self.load_dependencies: (*untyped) -> void
7
+ def self.configure: (singleton(Session)) -> void
8
+ def self.call: (Connection, Request, response) -> void
14
9
 
15
10
  class H2CParser < Connection::HTTP2
16
11
  def upgrade: (Request, Response) -> void
17
12
  end
18
13
 
19
14
  module ConnectionMethods
20
- def upgrade: (Request, Response) -> void
15
+ def upgrade_to_h2c: (Request, Response) -> void
21
16
  end
22
17
  end
23
18
 
@@ -6,7 +6,6 @@ module HTTPX
6
6
  interface _PersistentOptions
7
7
  def persistent: () -> bool?
8
8
  def persistent=: (bool) -> bool
9
- def with_persistent: (bool) -> instance
10
9
  end
11
10
 
12
11
  def self.extra_options: (Options) -> (Options & _PersistentOptions)
@@ -28,7 +28,6 @@ module HTTPX
28
28
  interface _ProxyOptions
29
29
  def proxy: () -> proxyParam?
30
30
  def proxy=: (Parameters | _ToHash) -> proxyParam
31
- def with_proxy: (Parameters | _ToHash) -> instance
32
31
  end
33
32
 
34
33
  def self.extra_options: (Options) -> (Options & _ProxyOptions)
@@ -12,19 +12,15 @@ module HTTPX
12
12
  interface _RetriesOptions
13
13
  def retry_after: () -> Numeric?
14
14
  def retry_after=: (Numeric) -> Numeric
15
- def with_retry_after: (Numeric) -> instance
16
15
 
17
16
  def max_retries: () -> Integer?
18
17
  def max_retries=: (int) -> Integer
19
- def with_max_retries: (int) -> instance
20
18
 
21
19
  def retry_change_requests: () -> bool?
22
20
  def retry_change_requests=: (bool) -> bool
23
- def with_retry_change_requests: (bool) -> instance
24
21
 
25
22
  def retry_on: () -> _RetryCallback?
26
23
  def retry_on=: (_RetryCallback) -> _RetryCallback
27
- def with_retry_on: (_RetryCallback) -> instance
28
24
  end
29
25
 
30
26
  def self.extra_options: (Options) -> (Options & _RetriesOptions)
@@ -0,0 +1,23 @@
1
+ module HTTPX
2
+ module Plugins
3
+ module Upgrade
4
+ type handlers_registry = Registry[Symbol, Class]
5
+
6
+ def self.configure: (singleton(Session)) -> void
7
+
8
+ interface _UpgradeOptions
9
+ def upgrade_handlers: () -> handlers_registry?
10
+ def upgrade_handlers=: (handlers_registry) -> handlers_registry
11
+ end
12
+
13
+ def self.extra_options: (Options) -> (Options & _UpgradeOptions)
14
+
15
+ module ConnectionMethods
16
+ attr_reader upgrade_protocol: Symbol?
17
+ attr_reader hijacked: boolish
18
+
19
+ def hijack_io: () -> void
20
+ end
21
+ end
22
+ end
23
+ end