httpx 0.12.0 → 0.14.1
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_10_1.md +1 -1
- data/doc/release_notes/0_13_0.md +58 -0
- data/doc/release_notes/0_13_1.md +5 -0
- data/doc/release_notes/0_13_2.md +9 -0
- data/doc/release_notes/0_14_0.md +79 -0
- data/doc/release_notes/0_14_1.md +7 -0
- data/lib/httpx.rb +1 -2
- data/lib/httpx/callbacks.rb +12 -3
- data/lib/httpx/chainable.rb +2 -2
- data/lib/httpx/connection.rb +29 -22
- data/lib/httpx/connection/http1.rb +35 -15
- data/lib/httpx/connection/http2.rb +61 -15
- data/lib/httpx/headers.rb +7 -3
- data/lib/httpx/io/ssl.rb +30 -17
- data/lib/httpx/io/tcp.rb +48 -27
- data/lib/httpx/io/udp.rb +31 -7
- data/lib/httpx/io/unix.rb +27 -12
- data/lib/httpx/options.rb +97 -74
- data/lib/httpx/plugins/aws_sdk_authentication.rb +5 -2
- data/lib/httpx/plugins/aws_sigv4.rb +5 -4
- data/lib/httpx/plugins/basic_authentication.rb +8 -3
- data/lib/httpx/plugins/compression.rb +24 -12
- data/lib/httpx/plugins/compression/brotli.rb +10 -7
- data/lib/httpx/plugins/compression/deflate.rb +6 -5
- data/lib/httpx/plugins/compression/gzip.rb +4 -3
- data/lib/httpx/plugins/cookies.rb +3 -7
- data/lib/httpx/plugins/digest_authentication.rb +5 -5
- data/lib/httpx/plugins/expect.rb +6 -6
- data/lib/httpx/plugins/follow_redirects.rb +4 -4
- data/lib/httpx/plugins/grpc.rb +247 -0
- data/lib/httpx/plugins/grpc/call.rb +62 -0
- data/lib/httpx/plugins/grpc/message.rb +85 -0
- data/lib/httpx/plugins/h2c.rb +43 -58
- data/lib/httpx/plugins/internal_telemetry.rb +1 -1
- data/lib/httpx/plugins/multipart/part.rb +2 -2
- data/lib/httpx/plugins/proxy.rb +3 -7
- data/lib/httpx/plugins/proxy/http.rb +5 -4
- data/lib/httpx/plugins/proxy/ssh.rb +3 -3
- data/lib/httpx/plugins/rate_limiter.rb +1 -1
- data/lib/httpx/plugins/retries.rb +14 -15
- data/lib/httpx/plugins/stream.rb +99 -75
- data/lib/httpx/plugins/upgrade.rb +84 -0
- data/lib/httpx/plugins/upgrade/h2.rb +54 -0
- data/lib/httpx/pool.rb +14 -5
- data/lib/httpx/request.rb +25 -2
- data/lib/httpx/resolver/native.rb +7 -3
- data/lib/httpx/response.rb +9 -5
- data/lib/httpx/session.rb +17 -7
- data/lib/httpx/transcoder/chunker.rb +1 -1
- data/lib/httpx/version.rb +1 -1
- data/sig/callbacks.rbs +2 -0
- data/sig/chainable.rbs +2 -1
- data/sig/connection/http1.rbs +6 -1
- data/sig/connection/http2.rbs +6 -2
- data/sig/headers.rbs +2 -2
- data/sig/options.rbs +16 -22
- data/sig/plugins/aws_sdk_authentication.rbs +2 -0
- data/sig/plugins/aws_sigv4.rbs +0 -1
- data/sig/plugins/basic_authentication.rbs +2 -0
- data/sig/plugins/compression.rbs +7 -5
- data/sig/plugins/compression/brotli.rbs +1 -1
- data/sig/plugins/compression/deflate.rbs +1 -1
- data/sig/plugins/compression/gzip.rbs +1 -1
- data/sig/plugins/cookies.rbs +0 -1
- data/sig/plugins/digest_authentication.rbs +0 -1
- data/sig/plugins/expect.rbs +0 -2
- data/sig/plugins/follow_redirects.rbs +0 -2
- data/sig/plugins/h2c.rbs +5 -10
- data/sig/plugins/persistent.rbs +0 -1
- data/sig/plugins/proxy.rbs +0 -1
- data/sig/plugins/retries.rbs +0 -4
- data/sig/plugins/stream.rbs +17 -16
- data/sig/plugins/upgrade.rbs +23 -0
- data/sig/request.rbs +7 -2
- data/sig/response.rbs +4 -1
- data/sig/session.rbs +4 -0
- metadata +21 -7
- data/lib/httpx/timeout.rb +0 -67
- data/sig/timeout.rbs +0 -29
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HTTPX
|
4
|
+
module Plugins
|
5
|
+
module GRPC
|
6
|
+
# Encoding module for GRPC responses
|
7
|
+
#
|
8
|
+
# Can encode and decode grpc messages.
|
9
|
+
module Message
|
10
|
+
module_function
|
11
|
+
|
12
|
+
# decodes a unary grpc response
|
13
|
+
def unary(response)
|
14
|
+
verify_status(response)
|
15
|
+
decode(response.to_s, encodings: response.headers.get("grpc-encoding"), encoders: response.encoders)
|
16
|
+
end
|
17
|
+
|
18
|
+
# lazy decodes a grpc stream response
|
19
|
+
def stream(response, &block)
|
20
|
+
return enum_for(__method__, response) unless block_given?
|
21
|
+
|
22
|
+
response.each do |frame|
|
23
|
+
decode(frame, encodings: response.headers.get("grpc-encoding"), encoders: response.encoders, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
verify_status(response)
|
27
|
+
end
|
28
|
+
|
29
|
+
# encodes a single grpc message
|
30
|
+
def encode(bytes, deflater:)
|
31
|
+
if deflater
|
32
|
+
compressed_flag = 1
|
33
|
+
bytes = deflater.deflate(StringIO.new(bytes))
|
34
|
+
else
|
35
|
+
compressed_flag = 0
|
36
|
+
end
|
37
|
+
|
38
|
+
"".b << [compressed_flag, bytes.bytesize].pack("CL>") << bytes.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
# decodes a single grpc message
|
42
|
+
def decode(message, encodings:, encoders:)
|
43
|
+
until message.empty?
|
44
|
+
|
45
|
+
compressed, size = message.unpack("CL>")
|
46
|
+
|
47
|
+
data = message.byteslice(5..size + 5 - 1)
|
48
|
+
if compressed == 1
|
49
|
+
encodings.reverse_each do |algo|
|
50
|
+
inflater = encoders.registry(algo).inflater(size)
|
51
|
+
data = inflater.inflate(data)
|
52
|
+
size = data.bytesize
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
return data unless block_given?
|
57
|
+
|
58
|
+
yield data
|
59
|
+
|
60
|
+
message = message.byteslice(5 + size..-1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def cancel(request)
|
65
|
+
request.emit(:refuse, :client_cancellation)
|
66
|
+
end
|
67
|
+
|
68
|
+
# interprets the grpc call trailing metadata, and raises an
|
69
|
+
# exception in case of error code
|
70
|
+
def verify_status(response)
|
71
|
+
# return standard errors if need be
|
72
|
+
response.raise_for_status
|
73
|
+
|
74
|
+
status = Integer(response.headers["grpc-status"])
|
75
|
+
message = response.headers["grpc-message"]
|
76
|
+
|
77
|
+
return if status.zero?
|
78
|
+
|
79
|
+
response.close
|
80
|
+
raise GRPCError.new(status, message, response.trailing_metadata)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/httpx/plugins/h2c.rb
CHANGED
@@ -6,68 +6,53 @@ module HTTPX
|
|
6
6
|
# This plugin adds support for upgrading a plaintext HTTP/1.1 connection to HTTP/2
|
7
7
|
# (https://tools.ietf.org/html/rfc7540#section-3.2)
|
8
8
|
#
|
9
|
-
# https://gitlab.com/honeyryderchuck/httpx/wikis/
|
9
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Upgrade#h2c
|
10
10
|
#
|
11
11
|
module H2C
|
12
|
-
|
13
|
-
|
12
|
+
VALID_H2C_VERBS = %i[get options head].freeze
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def load_dependencies(*)
|
16
|
+
require "base64"
|
17
|
+
end
|
18
|
+
|
19
|
+
def configure(klass)
|
20
|
+
klass.plugin(:upgrade)
|
21
|
+
klass.default_options.upgrade_handlers.register "h2c", self
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(connection, request, response)
|
25
|
+
connection.upgrade_to_h2c(request, response)
|
26
|
+
end
|
14
27
|
end
|
15
28
|
|
16
29
|
module InstanceMethods
|
17
|
-
def
|
18
|
-
|
30
|
+
def send_requests(*requests, options)
|
31
|
+
upgrade_request, *remainder = requests
|
32
|
+
|
33
|
+
return super unless VALID_H2C_VERBS.include?(upgrade_request.verb) && upgrade_request.scheme == "http"
|
19
34
|
|
20
|
-
|
35
|
+
connection = pool.find_connection(upgrade_request.uri, @options.merge(options))
|
21
36
|
|
22
|
-
|
23
|
-
return super unless valid_h2c_upgrade_request?(upgrade_request)
|
37
|
+
return super if connection && connection.upgrade_protocol == :h2c
|
24
38
|
|
39
|
+
# build upgrade request
|
25
40
|
upgrade_request.headers.add("connection", "upgrade")
|
26
41
|
upgrade_request.headers.add("connection", "http2-settings")
|
27
42
|
upgrade_request.headers["upgrade"] = "h2c"
|
28
43
|
upgrade_request.headers["http2-settings"] = HTTP2Next::Client.settings_header(upgrade_request.options.http2_settings)
|
29
|
-
wrap { send_requests(*upgrade_request, h2c_options).first }
|
30
44
|
|
31
|
-
|
32
|
-
|
33
|
-
responses.size == 1 ? responses.first : responses
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def fetch_response(request, connections, options)
|
39
|
-
response = super
|
40
|
-
if response && valid_h2c_upgrade?(request, response, options)
|
41
|
-
log { "upgrading to h2c..." }
|
42
|
-
connection = find_connection(request, connections, options)
|
43
|
-
connections << connection unless connections.include?(connection)
|
44
|
-
connection.upgrade(request, response)
|
45
|
-
end
|
46
|
-
response
|
47
|
-
end
|
48
|
-
|
49
|
-
VALID_H2C_METHODS = %i[get options head].freeze
|
50
|
-
private_constant :VALID_H2C_METHODS
|
51
|
-
|
52
|
-
def valid_h2c_upgrade_request?(request)
|
53
|
-
VALID_H2C_METHODS.include?(request.verb) &&
|
54
|
-
request.scheme == "http"
|
55
|
-
end
|
56
|
-
|
57
|
-
def valid_h2c_upgrade?(request, response, options)
|
58
|
-
options.fallback_protocol == "h2c" &&
|
59
|
-
request.headers.get("connection").include?("upgrade") &&
|
60
|
-
request.headers.get("upgrade").include?("h2c") &&
|
61
|
-
response.status == 101
|
45
|
+
super(upgrade_request, *remainder, options.merge(max_concurrent_requests: 1))
|
62
46
|
end
|
63
47
|
end
|
64
48
|
|
65
49
|
class H2CParser < Connection::HTTP2
|
66
50
|
def upgrade(request, response)
|
67
|
-
@connection.send_connection_preface
|
68
51
|
# skip checks, it is assumed that this is the first
|
69
52
|
# request in the connection
|
70
53
|
stream = @connection.upgrade
|
54
|
+
|
55
|
+
# on_settings
|
71
56
|
handle_stream(stream, request)
|
72
57
|
@streams[request] = stream
|
73
58
|
|
@@ -81,29 +66,29 @@ module HTTPX
|
|
81
66
|
module ConnectionMethods
|
82
67
|
using URIExtensions
|
83
68
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
super && options.fallback_protocol == "h2c"
|
88
|
-
end
|
89
|
-
|
90
|
-
def coalescable?(connection)
|
91
|
-
return super unless @options.fallback_protocol == "h2c" && @origin.scheme == "http"
|
69
|
+
def upgrade_to_h2c(request, response)
|
70
|
+
prev_parser = @parser
|
92
71
|
|
93
|
-
|
94
|
-
|
72
|
+
if prev_parser
|
73
|
+
prev_parser.reset
|
74
|
+
@inflight -= prev_parser.requests.size
|
75
|
+
end
|
95
76
|
|
96
|
-
|
97
|
-
@parser
|
98
|
-
@parser = H2CParser.new(@write_buffer, @options)
|
77
|
+
parser_options = @options.merge(max_concurrent_requests: request.options.max_concurrent_requests)
|
78
|
+
@parser = H2CParser.new(@write_buffer, parser_options)
|
99
79
|
set_parser_callbacks(@parser)
|
80
|
+
@inflight += 1
|
100
81
|
@parser.upgrade(request, response)
|
101
|
-
|
82
|
+
@upgrade_protocol = :h2c
|
102
83
|
|
103
|
-
|
104
|
-
|
84
|
+
if request.options.max_concurrent_requests != @options.max_concurrent_requests
|
85
|
+
@options = @options.merge(max_concurrent_requests: nil)
|
86
|
+
end
|
105
87
|
|
106
|
-
|
88
|
+
prev_parser.requests.each do |req|
|
89
|
+
req.transition(:idle)
|
90
|
+
send(req)
|
91
|
+
end
|
107
92
|
end
|
108
93
|
end
|
109
94
|
end
|
@@ -71,7 +71,7 @@ module HTTPX
|
|
71
71
|
def transition(nextstate)
|
72
72
|
state = @state
|
73
73
|
super
|
74
|
-
meter_elapsed_time("Request[#{@verb} #{@uri}: #{state}] -> #{nextstate}") if nextstate == @state
|
74
|
+
meter_elapsed_time("Request##{object_id}[#{@verb} #{@uri}: #{state}] -> #{nextstate}") if nextstate == @state
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
@@ -19,14 +19,14 @@ module HTTPX
|
|
19
19
|
value = value[:body]
|
20
20
|
end
|
21
21
|
|
22
|
-
value = value.open(:binmode => true) if value.is_a?(Pathname)
|
22
|
+
value = value.open(:binmode => true) if Object.const_defined?(:Pathname) && value.is_a?(Pathname)
|
23
23
|
|
24
24
|
if value.is_a?(File)
|
25
25
|
filename ||= File.basename(value.path)
|
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"]
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
data/lib/httpx/plugins/proxy.rb
CHANGED
@@ -67,13 +67,9 @@ module HTTPX
|
|
67
67
|
|
68
68
|
def extra_options(options)
|
69
69
|
Class.new(options.class) do
|
70
|
-
def_option(:proxy)
|
71
|
-
|
72
|
-
|
73
|
-
else
|
74
|
-
Hash[pr]
|
75
|
-
end
|
76
|
-
end
|
70
|
+
def_option(:proxy, <<-OUT)
|
71
|
+
value.is_a?(#{Parameters}) ? value : Hash[value]
|
72
|
+
OUT
|
77
73
|
end.new(options)
|
78
74
|
end
|
79
75
|
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
|
|
@@ -25,37 +25,36 @@ module HTTPX
|
|
25
25
|
|
26
26
|
def self.extra_options(options)
|
27
27
|
Class.new(options.class) do
|
28
|
-
|
29
|
-
def_option(:retry_after) do |num|
|
28
|
+
def_option(:retry_after, <<-OUT)
|
30
29
|
# return early if callable
|
31
|
-
unless
|
32
|
-
|
33
|
-
raise Error, ":retry_after must be positive" unless
|
30
|
+
unless value.respond_to?(:call)
|
31
|
+
value = Integer(value)
|
32
|
+
raise Error, ":retry_after must be positive" unless value.positive?
|
34
33
|
end
|
35
34
|
|
36
|
-
|
37
|
-
|
35
|
+
value
|
36
|
+
OUT
|
38
37
|
|
39
|
-
def_option(:max_retries)
|
40
|
-
num = Integer(
|
38
|
+
def_option(:max_retries, <<-OUT)
|
39
|
+
num = Integer(value)
|
41
40
|
raise Error, ":max_retries must be positive" unless num.positive?
|
42
41
|
|
43
42
|
num
|
44
|
-
|
43
|
+
OUT
|
45
44
|
|
46
45
|
def_option(:retry_change_requests)
|
47
46
|
|
48
|
-
def_option(:retry_on)
|
49
|
-
raise ":retry_on must be called with the response" unless
|
47
|
+
def_option(:retry_on, <<-OUT)
|
48
|
+
raise ":retry_on must be called with the response" unless value.respond_to?(:call)
|
50
49
|
|
51
|
-
|
52
|
-
|
50
|
+
value
|
51
|
+
OUT
|
53
52
|
end.new(options).merge(max_retries: MAX_RETRIES)
|
54
53
|
end
|
55
54
|
|
56
55
|
module InstanceMethods
|
57
56
|
def max_retries(n)
|
58
|
-
|
57
|
+
with(max_retries: n.to_i)
|
59
58
|
end
|
60
59
|
|
61
60
|
private
|
data/lib/httpx/plugins/stream.rb
CHANGED
@@ -1,10 +1,99 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module HTTPX
|
4
|
+
class StreamResponse
|
5
|
+
def initialize(request, session, connections)
|
6
|
+
@request = request
|
7
|
+
@session = session
|
8
|
+
@connections = connections
|
9
|
+
@options = @request.options
|
10
|
+
end
|
11
|
+
|
12
|
+
def each(&block)
|
13
|
+
return enum_for(__method__) unless block_given?
|
14
|
+
|
15
|
+
raise Error, "response already streamed" if @response
|
16
|
+
|
17
|
+
@request.stream = self
|
18
|
+
|
19
|
+
begin
|
20
|
+
@on_chunk = block
|
21
|
+
|
22
|
+
if @request.response
|
23
|
+
# if we've already started collecting the payload, yield it first
|
24
|
+
# before proceeding
|
25
|
+
body = @request.response.body
|
26
|
+
|
27
|
+
body.each do |chunk|
|
28
|
+
on_chunk(chunk)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
response.raise_for_status
|
33
|
+
response.close
|
34
|
+
ensure
|
35
|
+
@on_chunk = nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def each_line
|
40
|
+
return enum_for(__method__) unless block_given?
|
41
|
+
|
42
|
+
line = +""
|
43
|
+
|
44
|
+
each do |chunk|
|
45
|
+
line << chunk
|
46
|
+
|
47
|
+
while (idx = line.index("\n"))
|
48
|
+
yield line.byteslice(0..idx - 1)
|
49
|
+
|
50
|
+
line = line.byteslice(idx + 1..-1)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# This is a ghost method. It's to be used ONLY internally, when processing streams
|
56
|
+
def on_chunk(chunk)
|
57
|
+
raise NoMethodError unless @on_chunk
|
58
|
+
|
59
|
+
@on_chunk.call(chunk)
|
60
|
+
end
|
61
|
+
|
62
|
+
# :nocov:
|
63
|
+
def inspect
|
64
|
+
"#<StreamResponse:#{object_id}>"
|
65
|
+
end
|
66
|
+
# :nocov:
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
response.to_s
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def response
|
75
|
+
@session.__send__(:receive_requests, [@request], @connections, @options) until @request.response
|
76
|
+
|
77
|
+
@request.response
|
78
|
+
end
|
79
|
+
|
80
|
+
def respond_to_missing?(meth, *args)
|
81
|
+
response.respond_to?(meth, *args) || super
|
82
|
+
end
|
83
|
+
|
84
|
+
def method_missing(meth, *args, &block)
|
85
|
+
return super unless response.respond_to?(meth)
|
86
|
+
|
87
|
+
response.__send__(meth, *args, &block)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
4
91
|
module Plugins
|
5
92
|
#
|
6
93
|
# This plugin adds support for stream response (text/event-stream).
|
7
94
|
#
|
95
|
+
# https://gitlab.com/honeyryderchuck/httpx/wikis/Stream
|
96
|
+
#
|
8
97
|
module Stream
|
9
98
|
module InstanceMethods
|
10
99
|
private
|
@@ -13,10 +102,13 @@ module HTTPX
|
|
13
102
|
return super(*args, **options) unless stream
|
14
103
|
|
15
104
|
requests = args.first.is_a?(Request) ? args : build_requests(*args, options)
|
16
|
-
|
17
105
|
raise Error, "only 1 response at a time is supported for streaming requests" unless requests.size == 1
|
18
106
|
|
19
|
-
|
107
|
+
request = requests.first
|
108
|
+
|
109
|
+
connections = _send_requests(requests, request.options)
|
110
|
+
|
111
|
+
StreamResponse.new(request, self, connections)
|
20
112
|
end
|
21
113
|
end
|
22
114
|
|
@@ -31,7 +123,7 @@ module HTTPX
|
|
31
123
|
end
|
32
124
|
|
33
125
|
module ResponseBodyMethods
|
34
|
-
def initialize(
|
126
|
+
def initialize(*)
|
35
127
|
super
|
36
128
|
@stream = @response.stream
|
37
129
|
end
|
@@ -51,78 +143,10 @@ module HTTPX
|
|
51
143
|
end
|
52
144
|
end
|
53
145
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
115
|
-
end
|
116
|
-
|
117
|
-
def respond_to_missing?(*args)
|
118
|
-
@options.response_class.respond_to?(*args) || super
|
119
|
-
end
|
120
|
-
|
121
|
-
def method_missing(meth, *args, &block)
|
122
|
-
return super unless @options.response_class.public_method_defined?(meth)
|
123
|
-
|
124
|
-
response.__send__(meth, *args, &block)
|
125
|
-
end
|
146
|
+
def self.const_missing(const_name)
|
147
|
+
super unless const_name == :StreamResponse
|
148
|
+
warn "DEPRECATION WARNING: the class #{self}::StreamResponse is deprecated. Use HTTPX::StreamResponse instead."
|
149
|
+
HTTPX::StreamResponse
|
126
150
|
end
|
127
151
|
end
|
128
152
|
register_plugin :stream, Stream
|