http2 0.0.24 → 0.0.25
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/Gemfile +1 -3
- data/Gemfile.lock +25 -19
- data/README.md +1 -0
- data/VERSION +1 -1
- data/http2.gemspec +16 -8
- data/include/connection.rb +142 -0
- data/include/get_request.rb +34 -0
- data/include/post_data_generator.rb +62 -0
- data/include/post_multipart_request.rb +113 -0
- data/include/post_request.rb +71 -0
- data/include/response.rb +17 -45
- data/include/response_reader.rb +101 -97
- data/include/url_builder.rb +58 -0
- data/lib/http2.rb +52 -315
- data/spec/http2/post_data_generator_spec.rb +24 -0
- data/spec/http2/url_builder_spec.rb +17 -0
- data/spec/http2_spec.rb +18 -24
- data/spec/spec_helper.rb +3 -1
- metadata +25 -18
- data/include/post_multipart_helper.rb +0 -77
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
class Http2::PostRequest
|
|
2
|
+
VALID_ARGUMENTS_POST = [:post, :url, :default_headers, :headers, :json, :method, :cookies, :on_content, :content_type]
|
|
3
|
+
|
|
4
|
+
def initialize(http2, args)
|
|
5
|
+
args.each do |key, val|
|
|
6
|
+
raise "Invalid key: '#{key}'." unless VALID_ARGUMENTS_POST.include?(key)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
@http2, @args, @debug, @nl = http2, http2.parse_args(args), http2.debug, http2.nl
|
|
10
|
+
@conn = @http2.connection
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def execute
|
|
14
|
+
@data = raw_data
|
|
15
|
+
|
|
16
|
+
@http2.mutex.synchronize do
|
|
17
|
+
puts "Http2: Doing post." if @debug
|
|
18
|
+
puts "Http2: Header str: #{header_str}" if @debug
|
|
19
|
+
|
|
20
|
+
@conn.write(header_string)
|
|
21
|
+
return @http2.read_response(@args)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def method
|
|
28
|
+
if @args[:method]
|
|
29
|
+
@args[:method].to_s.upcase
|
|
30
|
+
else
|
|
31
|
+
"POST"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def content_type
|
|
36
|
+
if @args[:content_type]
|
|
37
|
+
@args[:content_type]
|
|
38
|
+
elsif @args[:json]
|
|
39
|
+
content_type = "application/json"
|
|
40
|
+
else
|
|
41
|
+
"application/x-www-form-urlencoded"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def raw_data
|
|
46
|
+
if @args[:json]
|
|
47
|
+
require "json" unless ::Kernel.const_defined?(:JSON)
|
|
48
|
+
@args[:json].to_json
|
|
49
|
+
elsif @args[:post].is_a?(String)
|
|
50
|
+
@args[:post]
|
|
51
|
+
else
|
|
52
|
+
phash = @args[:post] ? @args[:post].clone : {}
|
|
53
|
+
@http2.autostate_set_on_post_hash(phash) if @http2.args[:autostate]
|
|
54
|
+
::Http2::PostDataGenerator.new(phash).generate
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def headers
|
|
59
|
+
headers_hash = {"Content-Length" => @data.bytesize, "Content-Type" => content_type}
|
|
60
|
+
headers_hash.merge! @http2.default_headers(@args)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def header_string
|
|
64
|
+
header_str = "#{method} /#{@args[:url]} HTTP/1.1#{@nl}"
|
|
65
|
+
header_str << @http2.header_str(headers, @args)
|
|
66
|
+
header_str << @nl
|
|
67
|
+
header_str << @data
|
|
68
|
+
|
|
69
|
+
header_str
|
|
70
|
+
end
|
|
71
|
+
end
|
data/include/response.rb
CHANGED
|
@@ -2,22 +2,23 @@
|
|
|
2
2
|
class Http2::Response
|
|
3
3
|
#All the data the response contains. Headers, body, cookies, requested URL and more.
|
|
4
4
|
attr_reader :args
|
|
5
|
-
|
|
5
|
+
attr_accessor :body, :charset, :code, :content_type, :http_version
|
|
6
|
+
|
|
6
7
|
#This method should not be called manually.
|
|
7
8
|
def initialize(args = {})
|
|
8
9
|
@args = args
|
|
9
10
|
@args[:headers] = {} if !@args.key?(:headers)
|
|
10
|
-
@args[:body]
|
|
11
|
+
@body = args[:body] || ""
|
|
11
12
|
@debug = @args[:debug]
|
|
12
13
|
end
|
|
13
|
-
|
|
14
|
+
|
|
14
15
|
#Returns headers given from the host for the result.
|
|
15
16
|
#===Examples
|
|
16
17
|
# headers_hash = res.headers
|
|
17
18
|
def headers
|
|
18
19
|
return @args[:headers]
|
|
19
20
|
end
|
|
20
|
-
|
|
21
|
+
|
|
21
22
|
#Returns a certain header by name or false if not found.
|
|
22
23
|
#===Examples
|
|
23
24
|
# val = res.header("content-type")
|
|
@@ -25,7 +26,7 @@ class Http2::Response
|
|
|
25
26
|
return false if !@args[:headers].key?(key)
|
|
26
27
|
return @args[:headers][key].first.to_s
|
|
27
28
|
end
|
|
28
|
-
|
|
29
|
+
|
|
29
30
|
#Returns true if a header of the given string exists.
|
|
30
31
|
#===Examples
|
|
31
32
|
# print "No content-type was given." if !http.header?("content-type")
|
|
@@ -33,40 +34,11 @@ class Http2::Response
|
|
|
33
34
|
return true if @args[:headers].key?(key) and @args[:headers][key].first.to_s.length > 0
|
|
34
35
|
return false
|
|
35
36
|
end
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# print "An internal error occurred." if res.code.to_i == 500
|
|
40
|
-
def code
|
|
41
|
-
return @args[:code]
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
#Returns the HTTP-version of the result.
|
|
45
|
-
#===Examples
|
|
46
|
-
# print "We are using HTTP 1.1 and should support keep-alive." if res.http_version.to_s == "1.1"
|
|
47
|
-
def http_version
|
|
48
|
-
return @args[:http_version]
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
#Returns the complete body of the result as a string.
|
|
52
|
-
#===Examples
|
|
53
|
-
# print "Looks like we caught the end of it as well?" if res.body.to_s.downcase.index("</html>") != nil
|
|
54
|
-
def body
|
|
55
|
-
return @args[:body]
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
#Returns the charset of the result.
|
|
59
|
-
def charset
|
|
60
|
-
return @args[:charset]
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
#Returns the content-type of the result as a string.
|
|
64
|
-
#===Examples
|
|
65
|
-
# print "This body can be printed - its just plain text!" if http.contenttype == "text/plain"
|
|
66
|
-
def contenttype
|
|
67
|
-
return @args[:contenttype]
|
|
37
|
+
|
|
38
|
+
def content_length
|
|
39
|
+
header("content-length").to_i if header?("content-length")
|
|
68
40
|
end
|
|
69
|
-
|
|
41
|
+
|
|
70
42
|
#Returns the requested URL as a string.
|
|
71
43
|
#===Examples
|
|
72
44
|
# res.requested_url #=> "?show=status&action=getstatus"
|
|
@@ -74,28 +46,28 @@ class Http2::Response
|
|
|
74
46
|
raise "URL could not be detected." if !@args[:request_args][:url]
|
|
75
47
|
return @args[:request_args][:url]
|
|
76
48
|
end
|
|
77
|
-
|
|
49
|
+
|
|
78
50
|
# Checks the data that has been sat on the object and raises various exceptions, if it does not validate somehow.
|
|
79
51
|
def validate!
|
|
80
52
|
puts "Http2: Validating response length." if @debug
|
|
81
53
|
validate_body_versus_content_length!
|
|
82
54
|
end
|
|
83
|
-
|
|
55
|
+
|
|
84
56
|
private
|
|
85
|
-
|
|
57
|
+
|
|
86
58
|
# Checks that the length of the body is the same as the given content-length if given.
|
|
87
59
|
def validate_body_versus_content_length!
|
|
88
60
|
unless self.header?("content-length")
|
|
89
61
|
puts "Http2: No content length given - skipping length validation." if @debug
|
|
90
62
|
return nil
|
|
91
63
|
end
|
|
92
|
-
|
|
64
|
+
|
|
93
65
|
content_length = self.header("content-length").to_i
|
|
94
|
-
body_length = @
|
|
95
|
-
|
|
66
|
+
body_length = @body.bytesize
|
|
67
|
+
|
|
96
68
|
puts "Http2: Body length: #{body_length}" if @debug
|
|
97
69
|
puts "Http2: Content length: #{content_length}" if @debug
|
|
98
|
-
|
|
70
|
+
|
|
99
71
|
raise "Body does not match the given content-length: '#{body_length}', '#{content_length}'." if body_length != content_length
|
|
100
72
|
end
|
|
101
73
|
end
|
data/include/response_reader.rb
CHANGED
|
@@ -6,23 +6,23 @@ class Http2::ResponseReader
|
|
|
6
6
|
@transfer_encoding = nil
|
|
7
7
|
@response = Http2::Response.new(:request_args => args, :debug => @debug)
|
|
8
8
|
@rec_count = 0
|
|
9
|
-
@args, @debug, @http2, @sock = args[:args], args[:debug
|
|
9
|
+
@args, @debug, @http2, @sock = args[:args], args[:http2].debug, args[:http2], args[:sock]
|
|
10
10
|
@nl = @http2.nl
|
|
11
|
+
@conn = @http2.connection
|
|
11
12
|
|
|
12
13
|
read_headers
|
|
13
|
-
read_body
|
|
14
|
+
read_body if @length == nil || @length > 0
|
|
14
15
|
finish
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def read_headers
|
|
18
19
|
loop do
|
|
19
|
-
line = @
|
|
20
|
+
line = @conn.gets
|
|
20
21
|
check_line_read(line)
|
|
21
22
|
|
|
22
23
|
if line == "\n" || line == "\r\n" || line == @nl
|
|
23
24
|
puts "Http2: Changing mode to body!" if @debug
|
|
24
25
|
raise "No headers was given at all? Possibly corrupt state after last request?" if @response.headers.empty?
|
|
25
|
-
break if @length == 0
|
|
26
26
|
@mode = "body"
|
|
27
27
|
@http2.on_content_call(@args, @nl)
|
|
28
28
|
break
|
|
@@ -34,71 +34,76 @@ class Http2::ResponseReader
|
|
|
34
34
|
|
|
35
35
|
def read_body
|
|
36
36
|
loop do
|
|
37
|
-
if @length
|
|
38
|
-
line = @
|
|
37
|
+
if @length
|
|
38
|
+
line = @conn.read(@length)
|
|
39
39
|
raise "Expected to get #{@length} of bytes but got #{line.bytesize}" if @length != line.bytesize
|
|
40
40
|
else
|
|
41
|
-
line = @
|
|
41
|
+
line = @conn.gets
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
check_line_read(line)
|
|
45
45
|
stat = parse_body(line)
|
|
46
|
-
break if stat ==
|
|
47
|
-
next if stat ==
|
|
46
|
+
break if stat == :break
|
|
47
|
+
next if stat == :next
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def finish
|
|
52
52
|
#Check if we should reconnect based on keep-alive-max.
|
|
53
|
-
if @keepalive_max == 1
|
|
54
|
-
@
|
|
53
|
+
if @keepalive_max == 1 || @connection == "close"
|
|
54
|
+
@conn.close unless @conn.closed?
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
# Validate that the response is as it should be.
|
|
58
58
|
puts "Http2: Validating response." if @debug
|
|
59
59
|
|
|
60
|
-
if !@response.
|
|
61
|
-
raise "No status-code was received from the server. Headers: '#{@response.headers}' Body: '#{resp.
|
|
60
|
+
if !@response.code
|
|
61
|
+
raise "No status-code was received from the server. Headers: '#{@response.headers}' Body: '#{resp.body}'."
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
@response.validate!
|
|
65
65
|
check_and_decode
|
|
66
|
-
|
|
66
|
+
@http2.autostate_register(@response) if @http2.args[:autostate]
|
|
67
67
|
handle_errors
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
if response = check_and_follow_redirect
|
|
70
|
+
@response = response
|
|
71
|
+
end
|
|
70
72
|
end
|
|
71
73
|
|
|
72
74
|
private
|
|
73
75
|
|
|
74
76
|
def check_and_follow_redirect
|
|
75
|
-
if (@response.
|
|
76
|
-
|
|
77
|
-
url = uri.path
|
|
78
|
-
url << "?#{uri.query}" if uri.query.to_s.length > 0
|
|
79
|
-
|
|
80
|
-
args = {:host => uri.host}
|
|
81
|
-
args[:ssl] = true if uri.scheme == "https"
|
|
82
|
-
args[:port] = uri.port if uri.port
|
|
77
|
+
if (@response.code == "302" || @response.code == "307") && @response.header?("location") && @http2.args[:follow_redirects]
|
|
78
|
+
url, args = url_and_args_from_location
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if !args[:host] or args[:host] == @args[:host]
|
|
87
|
-
return self.get(url)
|
|
80
|
+
if !args[:host] || args[:host] == @args[:host]
|
|
81
|
+
return @http2.get(url)
|
|
88
82
|
else
|
|
89
|
-
|
|
90
|
-
return http.get(url)
|
|
83
|
+
::Http2.new(args).get(url)
|
|
91
84
|
end
|
|
92
85
|
end
|
|
93
86
|
end
|
|
94
87
|
|
|
88
|
+
def url_and_args_from_location
|
|
89
|
+
uri = URI.parse(@response.header("location"))
|
|
90
|
+
url = uri.path
|
|
91
|
+
url << "?#{uri.query}" if uri.query.to_s.length > 0
|
|
92
|
+
|
|
93
|
+
args = {host: uri.host}
|
|
94
|
+
args[:ssl] = true if uri.scheme == "https"
|
|
95
|
+
args[:port] = uri.port if uri.port
|
|
96
|
+
|
|
97
|
+
return [url, args]
|
|
98
|
+
end
|
|
99
|
+
|
|
95
100
|
def check_and_decode
|
|
96
101
|
# Check if the content is gzip-encoded - if so: decode it!
|
|
97
102
|
if @encoding == "gzip"
|
|
98
103
|
puts "Http2: Decoding GZip." if @debug
|
|
99
104
|
require "zlib"
|
|
100
105
|
require "stringio"
|
|
101
|
-
io = StringIO.new(@response.
|
|
106
|
+
io = StringIO.new(@response.body)
|
|
102
107
|
gz = Zlib::GzipReader.new(io)
|
|
103
108
|
untrusted_str = gz.read
|
|
104
109
|
|
|
@@ -108,21 +113,21 @@ private
|
|
|
108
113
|
valid_string = untrusted_str.force_encoding("UTF-8").encode("UTF-8", :invalid => :replace, :replace => "").encode("UTF-8")
|
|
109
114
|
end
|
|
110
115
|
|
|
111
|
-
@response.
|
|
116
|
+
@response.body = valid_string
|
|
112
117
|
end
|
|
113
118
|
end
|
|
114
119
|
|
|
115
120
|
def handle_errors
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
return unless @http2.raise_errors
|
|
122
|
+
|
|
123
|
+
if @response.code == "500"
|
|
124
|
+
err = Http2::Errors::Internalserver.new("A internal server error occurred")
|
|
125
|
+
elsif @response.code == "403"
|
|
126
|
+
err = Http2::Errors::Noaccess.new("No access")
|
|
127
|
+
elsif @response.code == "400"
|
|
128
|
+
err = Http2::Errors::Badrequest.new("Bad request")
|
|
129
|
+
elsif @response.code == "404"
|
|
130
|
+
err = Http2::Errors::Notfound.new("Not found")
|
|
126
131
|
end
|
|
127
132
|
|
|
128
133
|
if err
|
|
@@ -135,8 +140,7 @@ private
|
|
|
135
140
|
if line
|
|
136
141
|
@rec_count += line.length
|
|
137
142
|
elsif !line && @rec_count <= 0
|
|
138
|
-
@
|
|
139
|
-
raise Errno::ECONNABORTED, "Server closed the connection before being able to read anything (KeepAliveMax: '#{@keepalive_max}', Connection: '#{@connection}', PID: '#{Process.pid}')."
|
|
143
|
+
raise Errno::ECONNABORTED, "Server closed the connection before being able to read anything (KeepAliveMax: '#{@http2.keepalive_max}', Connection: '#{@connection}', PID: '#{Process.pid}')."
|
|
140
144
|
end
|
|
141
145
|
end
|
|
142
146
|
|
|
@@ -147,26 +151,25 @@ private
|
|
|
147
151
|
end
|
|
148
152
|
|
|
149
153
|
def parse_keep_alive(keep_alive_line)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
keep_alive_line.scan(/([a-z]+)=(\d+)/) do |match|
|
|
155
|
+
if match[0] == "timeout"
|
|
156
|
+
puts "Http2: Keepalive-max set to: '#{@keepalive_max}'." if @debug
|
|
157
|
+
@http2.keepalive_timeout = match[1].to_i
|
|
158
|
+
elsif match[0] == "max"
|
|
159
|
+
puts "Http2: Keepalive-timeout set to: '#{@keepalive_timeout}'." if @debug
|
|
160
|
+
@http2.keepalive_max = match[1].to_i
|
|
161
|
+
end
|
|
158
162
|
end
|
|
159
163
|
end
|
|
160
164
|
|
|
161
165
|
def parse_content_type(content_type_line)
|
|
162
166
|
if match_charset = content_type_line.match(/\s*;\s*charset=(.+)/i)
|
|
163
167
|
@charset = match_charset[1].downcase
|
|
164
|
-
@response.
|
|
168
|
+
@response.charset = @charset
|
|
165
169
|
content_type_line.gsub!(match_charset[0], "")
|
|
166
170
|
end
|
|
167
171
|
|
|
168
|
-
@
|
|
169
|
-
@response.args[:contenttype] = @content_type_line
|
|
172
|
+
@response.content_type = @content_type_line
|
|
170
173
|
end
|
|
171
174
|
|
|
172
175
|
#Parse a header-line and saves it on the object.
|
|
@@ -174,56 +177,57 @@ private
|
|
|
174
177
|
# http.parse_header("Content-Type: text/html\r\n")
|
|
175
178
|
def parse_header(line)
|
|
176
179
|
if match = line.match(/^(.+?):\s*(.+)#{@nl}$/)
|
|
177
|
-
key = match[1].
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
elsif key == "content-length"
|
|
189
|
-
@length = match[2].to_i
|
|
190
|
-
elsif key == "transfer-encoding"
|
|
191
|
-
@transfer_encoding = match[2].to_s.downcase.strip
|
|
192
|
-
end
|
|
180
|
+
key = match[1].downcase
|
|
181
|
+
set_header_special_values(key, match[2])
|
|
182
|
+
parse_normal_header(line, key, match[1], match[2])
|
|
183
|
+
elsif match = line.match(/^HTTP\/([\d\.]+)\s+(\d+)\s+(.+)$/)
|
|
184
|
+
@response.code = match[2]
|
|
185
|
+
@response.http_version = match[1]
|
|
186
|
+
@http2.on_content_call(@args, line)
|
|
187
|
+
else
|
|
188
|
+
raise "Could not understand header string: '#{line}'."
|
|
189
|
+
end
|
|
190
|
+
end
|
|
193
191
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
192
|
+
def set_header_special_values(key, value)
|
|
193
|
+
parse_cookie(value) if key == "set-cookie"
|
|
194
|
+
parse_keep_alive(value) if key == "keep-alive"
|
|
195
|
+
parse_content_type(value) if key == "content-type"
|
|
196
|
+
|
|
197
|
+
if key == "connection"
|
|
198
|
+
@connection = value.downcase
|
|
199
|
+
elsif key == "content-encoding"
|
|
200
|
+
@encoding = value.downcase
|
|
201
|
+
puts "Http2: Setting encoding to #{@encoding}" if @debug
|
|
202
|
+
elsif key == "content-length"
|
|
203
|
+
@length = value.to_i
|
|
204
|
+
elsif key == "transfer-encoding"
|
|
205
|
+
@transfer_encoding = value.downcase.strip
|
|
206
|
+
end
|
|
207
|
+
end
|
|
197
208
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
@response.args[:code] = match[2]
|
|
203
|
-
@response.args[:http_version] = match[1]
|
|
209
|
+
def parse_normal_header(line, key, orig_key, value)
|
|
210
|
+
puts "Http2: Parsed header: #{orig_key}: #{value}" if @debug
|
|
211
|
+
@response.headers[key] = [] unless @response.headers.key?(key)
|
|
212
|
+
@response.headers[key] << value
|
|
204
213
|
|
|
214
|
+
if key != "transfer-encoding" && key != "content-length" && key != "connection" && key != "keep-alive"
|
|
205
215
|
@http2.on_content_call(@args, line)
|
|
206
|
-
else
|
|
207
|
-
raise "Could not understand header string: '#{line}'.\n\n#{@sock.read(409600)}"
|
|
208
216
|
end
|
|
209
217
|
end
|
|
210
218
|
|
|
211
219
|
#Parses the body based on given headers and saves it to the result-object.
|
|
212
220
|
# http.parse_body(str)
|
|
213
221
|
def parse_body(line)
|
|
214
|
-
if @
|
|
215
|
-
return "break" if @length == 0
|
|
222
|
+
return :break if @length == 0
|
|
216
223
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
else
|
|
220
|
-
puts "Http2: Adding #{line.to_s.bytesize} to the body." if @debug
|
|
221
|
-
@response.args[:body] << line.to_s
|
|
222
|
-
@http2.on_content_call(@args, line)
|
|
223
|
-
return "break" if @response.header?("content-length") && @response.args[:body].length >= @response.header("content-length").to_i
|
|
224
|
-
end
|
|
224
|
+
if @transfer_encoding == "chunked"
|
|
225
|
+
return parse_body_chunked(line)
|
|
225
226
|
else
|
|
226
|
-
|
|
227
|
+
puts "Http2: Adding #{line.to_s.bytesize} to the body." if @debug
|
|
228
|
+
@response.body << line
|
|
229
|
+
@http2.on_content_call(@args, line)
|
|
230
|
+
return :break if @response.content_length && @response.body.length >= @response.content_length
|
|
227
231
|
end
|
|
228
232
|
end
|
|
229
233
|
|
|
@@ -231,16 +235,16 @@ private
|
|
|
231
235
|
len = line.strip.hex
|
|
232
236
|
|
|
233
237
|
if len > 0
|
|
234
|
-
read = @
|
|
235
|
-
return
|
|
236
|
-
@response.
|
|
238
|
+
read = @conn.read(len)
|
|
239
|
+
return :break if read == "" || read == "\n" || read == "\r\n"
|
|
240
|
+
@response.body << read
|
|
237
241
|
@http2.on_content_call(@args, read)
|
|
238
242
|
end
|
|
239
243
|
|
|
240
|
-
nl = @
|
|
244
|
+
nl = @conn.gets
|
|
241
245
|
if len == 0
|
|
242
246
|
if nl == "\n" || nl == "\r\n"
|
|
243
|
-
return
|
|
247
|
+
return :break
|
|
244
248
|
else
|
|
245
249
|
raise "Dont know what to do :'-("
|
|
246
250
|
end
|