Permalink
Browse files

Allow chunked multipart POST of sized IO

Based on the fix for #117, this commit allows chunked multipart POST of
sized IO.  Fixes #112.
  • Loading branch information...
1 parent 8bb4854 commit 13c3f8715638302f6f117d370061fc9a63947f9f @nahi committed Oct 10, 2012
Showing with 24 additions and 5 deletions.
  1. +12 −3 lib/httpclient/http.rb
  2. +12 −2 test/test_httpclient.rb
View
@@ -542,7 +542,7 @@ def set_content(body, boundary = nil)
# bear in mind that server may not support it. at least ruby's CGI doesn't.
@body = body
remember_pos(@body)
- @size = body.respond_to?(:size) ? body.size - body.pos : nil
+ @size = (body.size - body.pos) rescue body.size if body.respond_to?(:size)
elsif boundary and Message.multiparam_query?(body)
@body = build_query_multipart_str(body, boundary)
@size = @body.size
@@ -554,11 +554,11 @@ def set_content(body, boundary = nil)
def remember_pos(io)
# IO may not support it (ex. IO.pipe)
- @positions[io] = io.pos if io.respond_to?(:pos)
+ @positions[io] = io.pos rescue nil if io.respond_to?(:pos)
end
def reset_pos(io)
- io.pos = @positions[io] if @positions.key?(io)
+ io.pos = @positions[io] if @positions[io]
end
def dump_file(io, dev)
@@ -578,12 +578,21 @@ def dump_file_length(io, size, dev)
end
def dump_chunks(io, dev)
+ return dump_chunks_length(io, io.size, dev) if io.respond_to?(:size) && io.size
buf = ''
while !io.read(@chunk_size, buf).nil?
dev << dump_chunk(buf)
end
end
+ def dump_chunks_length(io, size, dev)
+ buf = ''
+ while size > 0 && !(read = io.read(size > @chunk_size ? @chunk_size : size, buf)).nil?
+ dev << dump_chunk(buf)
+ size -= read.bytesize
+ end
+ end
+
def dump_chunk(str)
dump_chunk_size(str.bytesize) + (str + CRLF)
end
View
@@ -764,7 +764,7 @@ def myio.called
assert_match(/\r\n2\r\n/m, res.content)
assert_match(/\r\nContent-Disposition: form-data; name="3"; filename=""\r\n/m, res.content)
assert_match(/\r\nContent-Length:/m, str.string)
- assert_equal(3, myio.called)
+ assert_equal(2, myio.called, 'should just read 2 times, no need to extra read for detecting EOF')
end
def test_post_with_io_nosize # streaming + chunked post
@@ -781,7 +781,7 @@ def myio.size
assert_match(/\r\nTransfer-Encoding: chunked\r\n/m, str.string)
end
- def test_post_with_io_size_mismatch
+ def test_post_with_sized_io
myio = StringIO.new("45")
def myio.size
1
@@ -791,6 +791,16 @@ def myio.size
assert_match(/\r\n4\n/, str.string, 'should send "4" not "45"')
end
+ def test_post_with_sized_io_chunked
+ myio = StringIO.new("45")
+ def myio.size
+ 1
+ end
+ @client.debug_dev = str = StringIO.new
+ res = @client.post(serverurl + 'servlet', {:file => myio})
+ assert_match(/\r\n4\r\n/, str.string, 'should send "4" not "45"')
+ end
+
def test_post_async
param = {'1'=>'2', '3'=>'4'}
conn = @client.post_async(serverurl + 'servlet', param)

0 comments on commit 13c3f87

Please sign in to comment.