httpx 0.7.0 → 0.10.0
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/LICENSE.txt +48 -0
- data/README.md +9 -5
- data/doc/release_notes/0_0_1.md +7 -0
- data/doc/release_notes/0_0_2.md +9 -0
- data/doc/release_notes/0_0_3.md +9 -0
- data/doc/release_notes/0_0_4.md +7 -0
- data/doc/release_notes/0_0_5.md +5 -0
- data/doc/release_notes/0_10_0.md +66 -0
- data/doc/release_notes/0_1_0.md +9 -0
- data/doc/release_notes/0_2_0.md +5 -0
- data/doc/release_notes/0_2_1.md +16 -0
- data/doc/release_notes/0_3_0.md +12 -0
- data/doc/release_notes/0_3_1.md +6 -0
- data/doc/release_notes/0_4_0.md +51 -0
- data/doc/release_notes/0_4_1.md +3 -0
- data/doc/release_notes/0_5_0.md +15 -0
- data/doc/release_notes/0_5_1.md +14 -0
- data/doc/release_notes/0_6_0.md +5 -0
- data/doc/release_notes/0_6_1.md +6 -0
- data/doc/release_notes/0_6_2.md +6 -0
- data/doc/release_notes/0_6_3.md +13 -0
- data/doc/release_notes/0_6_4.md +21 -0
- data/doc/release_notes/0_6_5.md +22 -0
- data/doc/release_notes/0_6_6.md +19 -0
- data/doc/release_notes/0_6_7.md +5 -0
- data/doc/release_notes/0_7_0.md +46 -0
- data/doc/release_notes/0_8_0.md +27 -0
- data/doc/release_notes/0_8_1.md +8 -0
- data/doc/release_notes/0_8_2.md +7 -0
- data/doc/release_notes/0_9_0.md +38 -0
- data/lib/httpx.rb +2 -0
- data/lib/httpx/adapters/faraday.rb +1 -1
- data/lib/httpx/altsvc.rb +18 -2
- data/lib/httpx/chainable.rb +9 -8
- data/lib/httpx/connection.rb +177 -72
- data/lib/httpx/connection/http1.rb +44 -13
- data/lib/httpx/connection/http2.rb +77 -34
- data/lib/httpx/domain_name.rb +440 -0
- data/lib/httpx/errors.rb +1 -0
- data/lib/httpx/extensions.rb +23 -3
- data/lib/httpx/headers.rb +2 -2
- data/lib/httpx/io/ssl.rb +11 -4
- data/lib/httpx/io/tcp.rb +16 -5
- data/lib/httpx/io/udp.rb +4 -1
- data/lib/httpx/loggable.rb +6 -6
- data/lib/httpx/options.rb +22 -15
- data/lib/httpx/parser/http1.rb +14 -17
- data/lib/httpx/plugins/compression.rb +49 -64
- data/lib/httpx/plugins/compression/brotli.rb +10 -14
- data/lib/httpx/plugins/compression/deflate.rb +7 -6
- data/lib/httpx/plugins/compression/gzip.rb +45 -17
- data/lib/httpx/plugins/cookies.rb +21 -60
- data/lib/httpx/plugins/cookies/cookie.rb +173 -0
- data/lib/httpx/plugins/cookies/jar.rb +74 -0
- data/lib/httpx/plugins/cookies/set_cookie_parser.rb +142 -0
- data/lib/httpx/plugins/digest_authentication.rb +2 -0
- data/lib/httpx/plugins/expect.rb +12 -1
- data/lib/httpx/plugins/follow_redirects.rb +20 -2
- data/lib/httpx/plugins/h2c.rb +1 -1
- data/lib/httpx/plugins/multipart.rb +0 -8
- data/lib/httpx/plugins/persistent.rb +6 -1
- data/lib/httpx/plugins/proxy.rb +16 -12
- data/lib/httpx/plugins/proxy/http.rb +7 -2
- data/lib/httpx/plugins/proxy/socks4.rb +4 -2
- data/lib/httpx/plugins/proxy/socks5.rb +5 -1
- data/lib/httpx/plugins/push_promise.rb +2 -2
- data/lib/httpx/plugins/rate_limiter.rb +51 -0
- data/lib/httpx/plugins/retries.rb +13 -6
- data/lib/httpx/plugins/stream.rb +109 -13
- data/lib/httpx/pool.rb +13 -15
- data/lib/httpx/registry.rb +2 -1
- data/lib/httpx/request.rb +14 -19
- data/lib/httpx/resolver.rb +7 -8
- data/lib/httpx/resolver/https.rb +22 -5
- data/lib/httpx/resolver/native.rb +27 -33
- data/lib/httpx/resolver/options.rb +2 -2
- data/lib/httpx/resolver/resolver_mixin.rb +1 -1
- data/lib/httpx/response.rb +22 -17
- data/lib/httpx/selector.rb +96 -97
- data/lib/httpx/session.rb +32 -24
- data/lib/httpx/timeout.rb +7 -1
- data/lib/httpx/transcoder/chunker.rb +0 -2
- data/lib/httpx/transcoder/form.rb +0 -6
- data/lib/httpx/transcoder/json.rb +0 -4
- data/lib/httpx/utils.rb +45 -0
- data/lib/httpx/version.rb +1 -1
- data/sig/buffer.rbs +24 -0
- data/sig/callbacks.rbs +14 -0
- data/sig/chainable.rbs +37 -0
- data/sig/connection.rbs +2 -0
- data/sig/connection/http2.rbs +4 -0
- data/sig/domain_name.rbs +17 -0
- data/sig/errors.rbs +3 -0
- data/sig/headers.rbs +42 -0
- data/sig/httpx.rbs +14 -0
- data/sig/loggable.rbs +11 -0
- data/sig/missing.rbs +12 -0
- data/sig/options.rbs +118 -0
- data/sig/parser/http1.rbs +50 -0
- data/sig/plugins/authentication.rbs +11 -0
- data/sig/plugins/basic_authentication.rbs +13 -0
- data/sig/plugins/compression.rbs +55 -0
- data/sig/plugins/compression/brotli.rbs +21 -0
- data/sig/plugins/compression/deflate.rbs +17 -0
- data/sig/plugins/compression/gzip.rbs +29 -0
- data/sig/plugins/cookies.rbs +26 -0
- data/sig/plugins/cookies/cookie.rbs +50 -0
- data/sig/plugins/cookies/jar.rbs +27 -0
- data/sig/plugins/digest_authentication.rbs +33 -0
- data/sig/plugins/expect.rbs +19 -0
- data/sig/plugins/follow_redirects.rbs +37 -0
- data/sig/plugins/h2c.rbs +26 -0
- data/sig/plugins/multipart.rbs +19 -0
- data/sig/plugins/persistent.rbs +17 -0
- data/sig/plugins/proxy.rbs +47 -0
- data/sig/plugins/proxy/http.rbs +14 -0
- data/sig/plugins/proxy/socks4.rbs +33 -0
- data/sig/plugins/proxy/socks5.rbs +36 -0
- data/sig/plugins/proxy/ssh.rbs +18 -0
- data/sig/plugins/push_promise.rbs +22 -0
- data/sig/plugins/rate_limiter.rbs +11 -0
- data/sig/plugins/retries.rbs +48 -0
- data/sig/plugins/stream.rbs +39 -0
- data/sig/pool.rbs +2 -0
- data/sig/registry.rbs +9 -0
- data/sig/request.rbs +61 -0
- data/sig/response.rbs +87 -0
- data/sig/session.rbs +49 -0
- data/sig/test.rbs +9 -0
- data/sig/timeout.rbs +29 -0
- data/sig/transcoder.rbs +16 -0
- data/sig/transcoder/body.rbs +18 -0
- data/sig/transcoder/chunker.rbs +32 -0
- data/sig/transcoder/form.rbs +16 -0
- data/sig/transcoder/json.rbs +14 -0
- metadata +120 -21
|
@@ -31,6 +31,10 @@ module HTTPX
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def connecting?
|
|
35
|
+
super || @state == :authenticating || @state == :negotiating
|
|
36
|
+
end
|
|
37
|
+
|
|
34
38
|
private
|
|
35
39
|
|
|
36
40
|
def transition(nextstate)
|
|
@@ -60,7 +64,7 @@ module HTTPX
|
|
|
60
64
|
|
|
61
65
|
@parser = nil
|
|
62
66
|
end
|
|
63
|
-
log(level: 1
|
|
67
|
+
log(level: 1) { "SOCKS5: #{nextstate}: #{@write_buffer.to_s.inspect}" } unless nextstate == :open
|
|
64
68
|
super
|
|
65
69
|
end
|
|
66
70
|
|
|
@@ -43,9 +43,9 @@ module HTTPX
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def __on_promise_request(parser, stream, h)
|
|
46
|
-
log(level: 1
|
|
46
|
+
log(level: 1) do
|
|
47
47
|
# :nocov:
|
|
48
|
-
h.map { |k, v| "-> PROMISE HEADER: #{k}: #{v}" }.join("\n")
|
|
48
|
+
h.map { |k, v| "#{stream.id}: -> PROMISE HEADER: #{k}: #{v}" }.join("\n")
|
|
49
49
|
# :nocov:
|
|
50
50
|
end
|
|
51
51
|
headers = @options.headers_class.new(h)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module HTTPX
|
|
4
|
+
module Plugins
|
|
5
|
+
#
|
|
6
|
+
# This plugin adds support for retrying requests when the request:
|
|
7
|
+
#
|
|
8
|
+
# * is rate limited;
|
|
9
|
+
# * when the server is unavailable (503);
|
|
10
|
+
# * when a 3xx request comes with a "retry-after" value
|
|
11
|
+
#
|
|
12
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/RateLimiter
|
|
13
|
+
#
|
|
14
|
+
module RateLimiter
|
|
15
|
+
class << self
|
|
16
|
+
RATE_LIMIT_CODES = [429, 503].freeze
|
|
17
|
+
|
|
18
|
+
def load_dependencies(klass)
|
|
19
|
+
klass.plugin(:retries,
|
|
20
|
+
retry_change_requests: true,
|
|
21
|
+
retry_on: method(:retry_on_rate_limited_response),
|
|
22
|
+
retry_after: method(:retry_after_rate_limit))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def retry_on_rate_limited_response(response)
|
|
26
|
+
status = response.status
|
|
27
|
+
|
|
28
|
+
RATE_LIMIT_CODES.include?(status)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Servers send the "Retry-After" header field to indicate how long the
|
|
32
|
+
# user agent ought to wait before making a follow-up request. When
|
|
33
|
+
# sent with a 503 (Service Unavailable) response, Retry-After indicates
|
|
34
|
+
# how long the service is expected to be unavailable to the client.
|
|
35
|
+
# When sent with any 3xx (Redirection) response, Retry-After indicates
|
|
36
|
+
# the minimum time that the user agent is asked to wait before issuing
|
|
37
|
+
# the redirected request.
|
|
38
|
+
#
|
|
39
|
+
def retry_after_rate_limit(_, response)
|
|
40
|
+
retry_after = response.headers["retry-after"]
|
|
41
|
+
|
|
42
|
+
return unless retry_after
|
|
43
|
+
|
|
44
|
+
Utils.parse_retry_after(retry_after)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
register_plugin :rate_limiter, RateLimiter
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -63,20 +63,27 @@ module HTTPX
|
|
|
63
63
|
def fetch_response(request, connections, options)
|
|
64
64
|
response = super
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if response.is_a?(ErrorResponse) &&
|
|
66
|
+
if response &&
|
|
69
67
|
request.retries.positive? &&
|
|
70
68
|
__repeatable_request?(request, options) &&
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
(
|
|
70
|
+
# rubocop:disable Style/MultilineTernaryOperator
|
|
71
|
+
options.retry_on ?
|
|
72
|
+
options.retry_on.call(response) :
|
|
73
|
+
(
|
|
74
|
+
response.is_a?(ErrorResponse) && __retryable_error?(response.error)
|
|
75
|
+
)
|
|
76
|
+
# rubocop:enable Style/MultilineTernaryOperator
|
|
77
|
+
)
|
|
78
|
+
response.close if response.respond_to?(:close)
|
|
73
79
|
request.retries -= 1
|
|
74
80
|
log { "failed to get response, #{request.retries} tries to go..." }
|
|
75
81
|
request.transition(:idle)
|
|
76
82
|
|
|
77
83
|
retry_after = options.retry_after
|
|
84
|
+
retry_after = retry_after.call(request, response) if retry_after.respond_to?(:call)
|
|
85
|
+
|
|
78
86
|
if retry_after
|
|
79
|
-
retry_after = retry_after.call(request) if retry_after.respond_to?(:call)
|
|
80
87
|
|
|
81
88
|
log { "retrying after #{retry_after} secs..." }
|
|
82
89
|
pool.after(retry_after) do
|
data/lib/httpx/plugins/stream.rb
CHANGED
|
@@ -7,27 +7,123 @@ module HTTPX
|
|
|
7
7
|
#
|
|
8
8
|
module Stream
|
|
9
9
|
module InstanceMethods
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def request(*args, stream: false, **options)
|
|
13
|
+
return super(*args, **options) unless stream
|
|
14
|
+
|
|
15
|
+
requests = args.first.is_a?(Request) ? args : build_requests(*args, options)
|
|
16
|
+
|
|
17
|
+
raise Error, "only 1 response at a time is supported for streaming requests" unless requests.size == 1
|
|
18
|
+
|
|
19
|
+
StreamResponse.new(requests.first, self)
|
|
13
20
|
end
|
|
14
21
|
end
|
|
15
22
|
|
|
23
|
+
module RequestMethods
|
|
24
|
+
attr_accessor :stream
|
|
25
|
+
end
|
|
26
|
+
|
|
16
27
|
module ResponseMethods
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
def stream
|
|
29
|
+
@request.stream
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module ResponseBodyMethods
|
|
34
|
+
def initialize(*, **)
|
|
35
|
+
super
|
|
36
|
+
@stream = @response.stream
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def write(chunk)
|
|
40
|
+
return super unless @stream
|
|
41
|
+
|
|
42
|
+
@stream.on_chunk(chunk.to_s.dup)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def transition(*)
|
|
48
|
+
return if @stream
|
|
49
|
+
|
|
50
|
+
super
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class StreamResponse
|
|
55
|
+
def initialize(request, session)
|
|
56
|
+
@request = request
|
|
57
|
+
@session = session
|
|
58
|
+
@options = @request.options
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def each(&block)
|
|
62
|
+
return enum_for(__method__) unless block_given?
|
|
63
|
+
|
|
64
|
+
raise Error, "response already streamed" if @response
|
|
65
|
+
|
|
66
|
+
@request.stream = self
|
|
67
|
+
|
|
68
|
+
begin
|
|
69
|
+
@on_chunk = block
|
|
70
|
+
|
|
71
|
+
response.raise_for_status
|
|
72
|
+
response.close
|
|
73
|
+
ensure
|
|
74
|
+
@on_chunk = nil
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def each_line
|
|
79
|
+
return enum_for(__method__) unless block_given?
|
|
80
|
+
|
|
81
|
+
line = +""
|
|
82
|
+
|
|
83
|
+
each do |chunk|
|
|
84
|
+
line << chunk
|
|
85
|
+
|
|
86
|
+
while (idx = line.index("\n"))
|
|
87
|
+
yield line.byteslice(0..idx - 1)
|
|
88
|
+
|
|
89
|
+
line = line.byteslice(idx + 1..-1)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# This is a ghost method. It's to be used ONLY internally, when processing streams
|
|
95
|
+
def on_chunk(chunk)
|
|
96
|
+
raise NoMethodError unless @on_chunk
|
|
97
|
+
|
|
98
|
+
@on_chunk.call(chunk)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# :nocov:
|
|
102
|
+
def inspect
|
|
103
|
+
"#<StreamResponse:#{object_id}>"
|
|
104
|
+
end
|
|
105
|
+
# :nocov:
|
|
106
|
+
|
|
107
|
+
def to_s
|
|
108
|
+
response.to_s
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def response
|
|
114
|
+
@response ||= @session.__send__(:send_requests, @request, @options).first
|
|
21
115
|
end
|
|
22
116
|
|
|
23
|
-
def
|
|
24
|
-
@
|
|
117
|
+
def respond_to_missing?(*args)
|
|
118
|
+
@options.response_class.respond_to?(*args) || super
|
|
25
119
|
end
|
|
26
120
|
|
|
27
|
-
def
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
121
|
+
def method_missing(meth, *args, &block)
|
|
122
|
+
if @options.response_class.public_method_defined?(meth)
|
|
123
|
+
response.__send__(meth, *args, &block)
|
|
124
|
+
else
|
|
125
|
+
super
|
|
126
|
+
end
|
|
31
127
|
end
|
|
32
128
|
end
|
|
33
129
|
end
|
data/lib/httpx/pool.rb
CHANGED
|
@@ -14,7 +14,7 @@ module HTTPX
|
|
|
14
14
|
|
|
15
15
|
def initialize
|
|
16
16
|
@resolvers = {}
|
|
17
|
-
@
|
|
17
|
+
@_resolver_ios = {}
|
|
18
18
|
@timers = Timers::Group.new
|
|
19
19
|
@selector = Selector.new
|
|
20
20
|
@connections = []
|
|
@@ -28,28 +28,31 @@ module HTTPX
|
|
|
28
28
|
def next_tick
|
|
29
29
|
catch(:jump_tick) do
|
|
30
30
|
timeout = [next_timeout, @timers.wait_interval].compact.min
|
|
31
|
-
if timeout.negative?
|
|
31
|
+
if timeout && timeout.negative?
|
|
32
32
|
@timers.fire
|
|
33
33
|
throw(:jump_tick)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
@selector.select(timeout)
|
|
37
|
-
|
|
38
|
-
monitor.interests = monitor.io.interests
|
|
39
|
-
end
|
|
36
|
+
@selector.select(timeout, &:call)
|
|
37
|
+
|
|
40
38
|
@timers.fire
|
|
41
39
|
end
|
|
42
40
|
rescue StandardError => e
|
|
43
41
|
@connections.each do |connection|
|
|
44
42
|
connection.emit(:error, e)
|
|
45
43
|
end
|
|
44
|
+
rescue Exception # rubocop:disable Lint/RescueException
|
|
45
|
+
@connections.each(&:reset)
|
|
46
|
+
raise
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def close(connections = @connections)
|
|
50
|
+
return if connections.empty?
|
|
51
|
+
|
|
49
52
|
@timers.cancel
|
|
50
53
|
connections = connections.reject(&:inflight?)
|
|
51
54
|
connections.each(&:close)
|
|
52
|
-
next_tick until connections.none? { |c| @connections.include?(c) }
|
|
55
|
+
next_tick until connections.none? { |c| c.state != :idle && @connections.include?(c) }
|
|
53
56
|
@resolvers.each_value do |resolver|
|
|
54
57
|
resolver.close unless resolver.closed?
|
|
55
58
|
end if @connections.empty?
|
|
@@ -86,7 +89,7 @@ module HTTPX
|
|
|
86
89
|
resolver << connection
|
|
87
90
|
return if resolver.empty?
|
|
88
91
|
|
|
89
|
-
@
|
|
92
|
+
@_resolver_ios[resolver] ||= @selector.register(resolver)
|
|
90
93
|
end
|
|
91
94
|
|
|
92
95
|
def on_resolver_connection(connection)
|
|
@@ -118,8 +121,7 @@ module HTTPX
|
|
|
118
121
|
@resolvers.delete(resolver_type)
|
|
119
122
|
|
|
120
123
|
@selector.deregister(resolver)
|
|
121
|
-
|
|
122
|
-
monitor.close if monitor
|
|
124
|
+
@_resolver_ios.delete(resolver)
|
|
123
125
|
resolver.close unless resolver.closed?
|
|
124
126
|
end
|
|
125
127
|
|
|
@@ -128,10 +130,8 @@ module HTTPX
|
|
|
128
130
|
# if open, an IO was passed upstream, therefore
|
|
129
131
|
# consider it connected already.
|
|
130
132
|
@connected_connections += 1
|
|
131
|
-
@selector.register(connection, :rw)
|
|
132
|
-
else
|
|
133
|
-
@selector.register(connection, :w)
|
|
134
133
|
end
|
|
134
|
+
@selector.register(connection)
|
|
135
135
|
connection.on(:close) do
|
|
136
136
|
unregister_connection(connection)
|
|
137
137
|
end
|
|
@@ -168,7 +168,6 @@ module HTTPX
|
|
|
168
168
|
resolver.on(:error, &method(:on_resolver_error))
|
|
169
169
|
resolver.on(:close) { on_resolver_close(resolver) }
|
|
170
170
|
resolver
|
|
171
|
-
# rubocop: disable Layout/RescueEnsureAlignment
|
|
172
171
|
rescue ArgumentError
|
|
173
172
|
# this block is here because of an error which happens on CI from time to time
|
|
174
173
|
warn "tried resolver: #{resolver_type}"
|
|
@@ -176,7 +175,6 @@ module HTTPX
|
|
|
176
175
|
warn "new: #{resolver_type.method(:new).source_location}"
|
|
177
176
|
raise
|
|
178
177
|
end
|
|
179
|
-
# rubocop: enable Layout/RescueEnsureAlignment
|
|
180
178
|
end
|
|
181
179
|
end
|
|
182
180
|
end
|
data/lib/httpx/registry.rb
CHANGED
data/lib/httpx/request.rb
CHANGED
|
@@ -33,11 +33,7 @@ module HTTPX
|
|
|
33
33
|
|
|
34
34
|
USER_AGENT = "httpx.rb/#{VERSION}"
|
|
35
35
|
|
|
36
|
-
attr_reader :verb, :uri, :headers, :body, :state
|
|
37
|
-
|
|
38
|
-
attr_reader :options, :response
|
|
39
|
-
|
|
40
|
-
def_delegator :@body, :<<
|
|
36
|
+
attr_reader :verb, :uri, :headers, :body, :state, :options, :response
|
|
41
37
|
|
|
42
38
|
def_delegator :@body, :empty?
|
|
43
39
|
|
|
@@ -45,7 +41,7 @@ module HTTPX
|
|
|
45
41
|
|
|
46
42
|
def initialize(verb, uri, options = {})
|
|
47
43
|
@verb = verb.to_s.downcase.to_sym
|
|
48
|
-
@uri =
|
|
44
|
+
@uri = Utils.uri(uri)
|
|
49
45
|
@options = Options.new(options)
|
|
50
46
|
|
|
51
47
|
raise(Error, "unknown method: #{verb}") unless METHODS.include?(@verb)
|
|
@@ -58,17 +54,21 @@ module HTTPX
|
|
|
58
54
|
@state = :idle
|
|
59
55
|
end
|
|
60
56
|
|
|
61
|
-
|
|
57
|
+
def interests
|
|
58
|
+
return :r if @state == :done || @state == :expect
|
|
59
|
+
|
|
60
|
+
:w
|
|
61
|
+
end
|
|
62
|
+
|
|
62
63
|
if RUBY_VERSION < "2.2"
|
|
63
|
-
|
|
64
|
+
URIParser = URI::DEFAULT_PARSER
|
|
65
|
+
|
|
64
66
|
def initialize_with_escape(verb, uri, options = {})
|
|
65
|
-
initialize_without_escape(verb,
|
|
67
|
+
initialize_without_escape(verb, URIParser.escape(uri.to_s), options)
|
|
66
68
|
end
|
|
67
69
|
alias_method :initialize_without_escape, :initialize
|
|
68
70
|
alias_method :initialize, :initialize_with_escape
|
|
69
|
-
# rubocop: enable Lint/UriEscapeUnescape:
|
|
70
71
|
end
|
|
71
|
-
# :nocov:
|
|
72
72
|
|
|
73
73
|
def merge_headers(h)
|
|
74
74
|
@headers = @headers.merge(h)
|
|
@@ -174,19 +174,13 @@ module HTTPX
|
|
|
174
174
|
return true if @body.nil?
|
|
175
175
|
return false if chunked?
|
|
176
176
|
|
|
177
|
-
bytesize.zero?
|
|
177
|
+
@body.bytesize.zero?
|
|
178
178
|
end
|
|
179
179
|
|
|
180
180
|
def bytesize
|
|
181
181
|
return 0 if @body.nil?
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
@body.bytesize
|
|
185
|
-
elsif @body.respond_to?(:size)
|
|
186
|
-
@body.size
|
|
187
|
-
else
|
|
188
|
-
raise Error, "cannot determine size of body: #{@body.inspect}"
|
|
189
|
-
end
|
|
183
|
+
@body.bytesize
|
|
190
184
|
end
|
|
191
185
|
|
|
192
186
|
def stream(body)
|
|
@@ -219,6 +213,7 @@ module HTTPX
|
|
|
219
213
|
case nextstate
|
|
220
214
|
when :idle
|
|
221
215
|
@response = nil
|
|
216
|
+
@drainer = nil
|
|
222
217
|
when :headers
|
|
223
218
|
return unless @state == :idle
|
|
224
219
|
when :body
|
data/lib/httpx/resolver.rb
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "resolv"
|
|
4
|
+
require "httpx/resolver/resolver_mixin"
|
|
5
|
+
require "httpx/resolver/system"
|
|
6
|
+
require "httpx/resolver/native"
|
|
7
|
+
require "httpx/resolver/https"
|
|
4
8
|
|
|
5
9
|
module HTTPX
|
|
6
10
|
module Resolver
|
|
7
|
-
autoload :ResolverMixin, "httpx/resolver/resolver_mixin"
|
|
8
|
-
autoload :System, "httpx/resolver/system"
|
|
9
|
-
autoload :Native, "httpx/resolver/native"
|
|
10
|
-
autoload :HTTPS, "httpx/resolver/https"
|
|
11
|
-
|
|
12
11
|
extend Registry
|
|
13
12
|
|
|
14
|
-
register :system,
|
|
15
|
-
register :native,
|
|
16
|
-
register :https,
|
|
13
|
+
register :system, System
|
|
14
|
+
register :native, Native
|
|
15
|
+
register :https, HTTPS
|
|
17
16
|
|
|
18
17
|
@lookup_mutex = Mutex.new
|
|
19
18
|
@lookups = Hash.new { |h, k| h[k] = [] }
|