Skip to content

Commit 07c1f39

Browse files
committed
feat: Make connection IO.copy_stream compatible
1 parent e0382ac commit 07c1f39

3 files changed

Lines changed: 33 additions & 12 deletions

File tree

lib/http/connection.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def initialize(req, options)
3434
@pending_request = false
3535
@pending_response = false
3636
@failed_proxy_connect = false
37-
@buffer = "".b
37+
@buffer = String.new(capacity: BUFFER_SIZE, encoding: Encoding::BINARY)
3838

3939
@parser = Response::Parser.new
4040

@@ -89,19 +89,18 @@ def send_request(req)
8989
# Read a chunk of the body
9090
#
9191
# @return [String] data chunk
92-
# @return [nil] when no more data left
92+
# @raise [EOFError] when there's no more data left
9393
def readpartial(size = BUFFER_SIZE, outbuf = nil)
94-
return unless @pending_response
94+
raise EOFError unless @pending_response
9595

9696
chunk = @parser.read(size)
9797

9898
unless chunk
9999
finished = (read_more(size) == :eof) || @parser.finished?
100-
chunk = @parser.read(size)
100+
chunk = @parser.read(size) || String.new(encoding: Encoding::BINARY)
101101
finish_response if finished
102102
end
103103

104-
chunk ||= "".b
105104
outbuf ? outbuf.replace(chunk) : chunk
106105
end
107106

lib/http/response/body.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,16 @@ def to_s
4545

4646
raise StateError, "body is being streamed" unless @streaming.nil?
4747

48-
begin
49-
@streaming = false
50-
@contents = String.new("", encoding: @encoding)
48+
@streaming = false
49+
@contents = String.new("", encoding: @encoding)
5150

51+
begin
5252
while (chunk = @stream.readpartial)
5353
@contents << String.new(chunk, encoding: @encoding)
5454
chunk = nil # deallocate string
5555
end
56+
rescue EOFError
57+
# do nothing
5658
rescue
5759
@contents = nil
5860
raise

spec/lib/http/connection_spec.rb

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require "stringio"
4+
35
RSpec.describe HTTP::Connection do
46
let(:req) do
57
HTTP::Request.new(
@@ -77,10 +79,15 @@
7779
it "reads data in parts" do
7880
connection.read_headers!
7981
buffer = String.new
80-
while (s = connection.readpartial(3))
81-
expect(connection.finished_request?).to be false if s != ""
82-
buffer << s
82+
83+
begin
84+
while (s = connection.readpartial(3))
85+
expect(connection.finished_request?).to be false if s != ""
86+
buffer << s
87+
end
88+
rescue EOFError
8389
end
90+
8491
expect(buffer).to eq "1234567890"
8592
expect(connection.finished_request?).to be true
8693
end
@@ -89,8 +96,21 @@
8996
connection.read_headers!
9097
outbuf = String.new
9198
buffer = String.new
92-
buffer << outbuf while connection.readpartial(2, outbuf)
99+
100+
begin
101+
buffer << outbuf while connection.readpartial(2, outbuf)
102+
rescue EOFError
103+
end
104+
93105
expect(buffer).to eq "1234567890"
94106
end
107+
108+
it "can be used with IO.copy_stream" do
109+
output = StringIO.new
110+
111+
IO.copy_stream(connection, output)
112+
113+
expect(output.string).to eq "1234567890"
114+
end
95115
end
96116
end

0 commit comments

Comments
 (0)