diff --git a/lib/rest_client.rb b/lib/rest_client.rb index bf4c702..20b1f07 100644 --- a/lib/rest_client.rb +++ b/lib/rest_client.rb @@ -148,6 +148,8 @@ module RestClient raise RestClient::ServerBrokeConnection rescue Timeout::Error raise RestClient::RequestTimeout + ensure + payload.close end def setup_credentials(req) diff --git a/lib/rest_client/payload.rb b/lib/rest_client/payload.rb index 69aa6c1..803d323 100644 --- a/lib/rest_client/payload.rb +++ b/lib/rest_client/payload.rb @@ -48,7 +48,10 @@ module RestClient end alias :length :size - + def close + @stream.close + end + end class UrlEncoded < Base @@ -63,7 +66,7 @@ module RestClient def headers super.merge({'Content-Type' => 'application/x-www-form-urlencoded'}) end - + end class Multipart < Base @@ -95,11 +98,15 @@ module RestClient end def create_file_field(s, k, v) - s.write("Content-Disposition: multipart/form-data; name=\"#{k}\"; filename=\"#{v.path}\"#{EOL}") - s.write("Content-Type: #{mime_for(v.path)}#{EOL}") - s.write(EOL) - while data = v.read(8124) - s.write(data) + begin + s.write("Content-Disposition: multipart/form-data; name=\"#{k}\"; filename=\"#{v.path}\"#{EOL}") + s.write("Content-Type: #{mime_for(v.path)}#{EOL}") + s.write(EOL) + while data = v.read(8124) + s.write(data) + end + ensure + v.close end end @@ -115,6 +122,10 @@ module RestClient def headers super.merge({'Content-Type' => %Q{multipart/form-data; boundary="#{boundary}"}}) end + + def close + @stream.close + end end diff --git a/spec/base.rb b/spec/base.rb index 192612c..cdef584 100644 --- a/spec/base.rb +++ b/spec/base.rb @@ -2,3 +2,4 @@ require 'rubygems' require 'spec' require File.dirname(__FILE__) + '/../lib/rest_client' + diff --git a/spec/rest_client_spec.rb b/spec/rest_client_spec.rb index f875c20..865ff72 100644 --- a/spec/rest_client_spec.rb +++ b/spec/rest_client_spec.rb @@ -1,6 +1,11 @@ require File.dirname(__FILE__) + '/base' describe RestClient do + + def generate_payload(v) + RestClient::Payload::Base.new(v) + end + context "public API" do it "GET" do RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {}) @@ -104,9 +109,9 @@ describe RestClient do end it "transmits the request with Net::HTTP" do - @http.should_receive(:request).with('req', 'payload') + @http.should_receive(:request).with('req', be_kind_of(RestClient::Payload::Base)) @request.should_receive(:process_result) - @request.transmit(@uri, 'req', 'payload') + @request.transmit(@uri, 'req', generate_payload('payload')) end it "uses SSL when the URI refers to a https address" do @@ -114,13 +119,7 @@ describe RestClient do @net.should_receive(:use_ssl=).with(true) @http.stub!(:request) @request.stub!(:process_result) - @request.transmit(@uri, 'req', 'payload') - end - - it "doesn't send nil payloads" do - @http.should_receive(:request).with('req', '') - @request.should_receive(:process_result) - @request.transmit(@uri, 'req', nil) + @request.transmit(@uri, 'req', generate_payload('payload')) end it "passes non-hash payloads straight through" do @@ -151,7 +150,7 @@ describe RestClient do @request.stub!(:password).and_return('mypass') @request.should_receive(:setup_credentials).with('req') - @request.transmit(@uri, 'req', nil) + @request.transmit(@uri, 'req', generate_payload('')) end it "does not attempt to send any credentials if user is nil" do @@ -171,7 +170,8 @@ describe RestClient do it "catches EOFError and shows the more informative ServerBrokeConnection" do @http.stub!(:request).and_raise(EOFError) - lambda { @request.transmit(@uri, 'req', nil) }.should raise_error(RestClient::ServerBrokeConnection) + lambda { @request.transmit(@uri, 'req', generate_payload('')) }. + should raise_error(RestClient::ServerBrokeConnection) end it "execute calls execute_inner" do