esod-client 0.2.1 → 0.3.0

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.
Files changed (39) hide show
  1. data/VERSION +1 -1
  2. data/command_line_options.rb +3 -6
  3. data/esod-client.gemspec +29 -27
  4. data/lib/esod_client/esod_client.rb +2 -2
  5. data/lib/rest-client-1.4.2/README.rdoc +243 -0
  6. data/lib/rest-client-1.4.2/Rakefile +60 -0
  7. data/lib/rest-client-1.4.2/VERSION +1 -0
  8. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/bin/restclient +0 -0
  9. data/lib/rest-client-1.4.2/history.md +54 -0
  10. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/rest_client.rb +0 -0
  11. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient.rb +77 -21
  12. data/lib/rest-client-1.4.2/lib/restclient/abstract_response.rb +87 -0
  13. data/lib/rest-client-1.4.2/lib/restclient/exceptions.rb +146 -0
  14. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/net_http_ext.rb +0 -0
  15. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/payload.rb +15 -12
  16. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/raw_response.rb +7 -6
  17. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/request.rb +61 -89
  18. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/resource.rb +11 -10
  19. data/lib/rest-client-1.4.2/lib/restclient/response.rb +46 -0
  20. data/lib/{rest-client-1.2.0/spec/mixin/response_spec.rb → rest-client-1.4.2/spec/abstract_response_spec.rb} +3 -12
  21. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/base.rb +0 -0
  22. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/exceptions_spec.rb +23 -9
  23. data/lib/rest-client-1.4.2/spec/integration_spec.rb +38 -0
  24. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/master_shake.jpg +0 -0
  25. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/payload_spec.rb +20 -6
  26. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/raw_response_spec.rb +1 -1
  27. data/lib/rest-client-1.4.2/spec/request_spec.rb +518 -0
  28. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/resource_spec.rb +24 -0
  29. data/lib/rest-client-1.4.2/spec/response_spec.rb +130 -0
  30. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/restclient_spec.rb +21 -11
  31. metadata +38 -29
  32. data/lib/rest-client-1.2.0/README.rdoc +0 -102
  33. data/lib/rest-client-1.2.0/Rakefile +0 -57
  34. data/lib/rest-client-1.2.0/VERSION +0 -1
  35. data/lib/rest-client-1.2.0/lib/restclient/exceptions.rb +0 -89
  36. data/lib/rest-client-1.2.0/lib/restclient/mixin/response.rb +0 -48
  37. data/lib/rest-client-1.2.0/lib/restclient/response.rb +0 -20
  38. data/lib/rest-client-1.2.0/spec/request_spec.rb +0 -521
  39. data/lib/rest-client-1.2.0/spec/response_spec.rb +0 -21
@@ -10,6 +10,8 @@ describe RestClient::Payload do
10
10
  it "should form properly encoded params" do
11
11
  RestClient::Payload::UrlEncoded.new({:foo => 'bar'}).to_s.
12
12
  should == "foo=bar"
13
+ ["foo=bar&baz=qux", "baz=qux&foo=bar"].should include(
14
+ RestClient::Payload::UrlEncoded.new({:foo => 'bar', :baz => 'qux'}).to_s)
13
15
  end
14
16
 
15
17
  it "should properly handle hashes as parameter" do
@@ -19,6 +21,11 @@ describe RestClient::Payload do
19
21
  should == "foo[bar][baz]=qux"
20
22
  end
21
23
 
24
+ it "should handle many attributes inside a hash" do
25
+ parameters = RestClient::Payload::UrlEncoded.new({:foo => {:bar => 'baz', :baz => 'qux'}}).to_s
26
+ parameters.should include("foo[bar]=baz", "foo[baz]=qux")
27
+ end
28
+
22
29
  it "should form properly use symbols as parameters" do
23
30
  RestClient::Payload::UrlEncoded.new({:foo => :bar}).to_s.
24
31
  should == "foo=bar"
@@ -26,6 +33,13 @@ describe RestClient::Payload do
26
33
  should == "foo[bar]=baz"
27
34
  end
28
35
 
36
+ it "should properly handle arrays as repeated parameters" do
37
+ RestClient::Payload::UrlEncoded.new({:foo => ['bar']}).to_s.
38
+ should == "foo[]=bar"
39
+ RestClient::Payload::UrlEncoded.new({:foo => ['bar', 'baz']}).to_s.
40
+ should == "foo[]=bar&foo[]=baz"
41
+ end
42
+
29
43
  end
30
44
 
31
45
  context "A multipart Payload" do
@@ -39,11 +53,11 @@ describe RestClient::Payload do
39
53
  m = RestClient::Payload::Multipart.new([[:bar, "baz"], [:foo, "bar"]])
40
54
  m.to_s.should == <<-EOS
41
55
  --#{m.boundary}\r
42
- Content-Disposition: multipart/form-data; name="bar"\r
56
+ Content-Disposition: form-data; name="bar"\r
43
57
  \r
44
58
  baz\r
45
59
  --#{m.boundary}\r
46
- Content-Disposition: multipart/form-data; name="foo"\r
60
+ Content-Disposition: form-data; name="foo"\r
47
61
  \r
48
62
  bar\r
49
63
  --#{m.boundary}--\r
@@ -55,7 +69,7 @@ bar\r
55
69
  m = RestClient::Payload::Multipart.new({:foo => f})
56
70
  m.to_s.should == <<-EOS
57
71
  --#{m.boundary}\r
58
- Content-Disposition: multipart/form-data; name="foo"; filename="master_shake.jpg"\r
72
+ Content-Disposition: form-data; name="foo"; filename="master_shake.jpg"\r
59
73
  Content-Type: image/jpeg\r
60
74
  \r
61
75
  #{IO.read(f.path)}\r
@@ -70,7 +84,7 @@ Content-Type: image/jpeg\r
70
84
  m = RestClient::Payload::Multipart.new({:foo => f})
71
85
  m.to_s.should == <<-EOS
72
86
  --#{m.boundary}\r
73
- Content-Disposition: multipart/form-data; name="foo"; filename="foo.txt"\r
87
+ Content-Disposition: form-data; name="foo"; filename="foo.txt"\r
74
88
  Content-Type: text/plain\r
75
89
  \r
76
90
  #{IO.read(f.path)}\r
@@ -82,7 +96,7 @@ Content-Type: text/plain\r
82
96
  m = RestClient::Payload::Multipart.new({:bar => {:baz => "foo"}})
83
97
  m.to_s.should == <<-EOS
84
98
  --#{m.boundary}\r
85
- Content-Disposition: multipart/form-data; name="bar[baz]"\r
99
+ Content-Disposition: form-data; name="bar[baz]"\r
86
100
  \r
87
101
  foo\r
88
102
  --#{m.boundary}--\r
@@ -94,7 +108,7 @@ foo\r
94
108
  m = RestClient::Payload::Multipart.new({:foo => {:bar => f}})
95
109
  m.to_s.should == <<-EOS
96
110
  --#{m.boundary}\r
97
- Content-Disposition: multipart/form-data; name="foo[bar]"; filename="foo.txt"\r
111
+ Content-Disposition: form-data; name="foo[bar]"; filename="foo.txt"\r
98
112
  Content-Type: text/plain\r
99
113
  \r
100
114
  #{IO.read(f.path)}\r
@@ -4,7 +4,7 @@ describe RestClient::RawResponse do
4
4
  before do
5
5
  @tf = mock("Tempfile", :read => "the answer is 42", :open => true)
6
6
  @net_http_res = mock('net http response')
7
- @response = RestClient::RawResponse.new(@tf, @net_http_res)
7
+ @response = RestClient::RawResponse.new(@tf, @net_http_res, {})
8
8
  end
9
9
 
10
10
  it "behaves like string" do
@@ -0,0 +1,518 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ require 'webmock/rspec'
4
+ include WebMock
5
+
6
+ describe RestClient::Request do
7
+ before do
8
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
9
+
10
+ @uri = mock("uri")
11
+ @uri.stub!(:request_uri).and_return('/resource')
12
+ @uri.stub!(:host).and_return('some')
13
+ @uri.stub!(:port).and_return(80)
14
+
15
+ @net = mock("net::http base")
16
+ @http = mock("net::http connection")
17
+ Net::HTTP.stub!(:new).and_return(@net)
18
+ @net.stub!(:start).and_yield(@http)
19
+ @net.stub!(:use_ssl=)
20
+ @net.stub!(:verify_mode=)
21
+ RestClient.log = nil
22
+ end
23
+
24
+ it "accept */* mimetype, preferring xml" do
25
+ @request.default_headers[:accept].should == '*/*; q=0.5, application/xml'
26
+ end
27
+
28
+ describe "compression" do
29
+
30
+ it "decodes an uncompressed result body by passing it straight through" do
31
+ RestClient::Request.decode(nil, 'xyz').should == 'xyz'
32
+ end
33
+
34
+ it "doesn't fail for nil bodies" do
35
+ RestClient::Request.decode('gzip', nil).should be_nil
36
+ end
37
+
38
+
39
+ it "decodes a gzip body" do
40
+ RestClient::Request.decode('gzip', "\037\213\b\b\006'\252H\000\003t\000\313T\317UH\257\312,HM\341\002\000G\242(\r\v\000\000\000").should == "i'm gziped\n"
41
+ end
42
+
43
+ it "ingores gzip for empty bodies" do
44
+ RestClient::Request.decode('gzip', '').should be_empty
45
+ end
46
+
47
+ it "decodes a deflated body" do
48
+ RestClient::Request.decode('deflate', "x\234+\316\317MUHIM\313I,IMQ(I\255(\001\000A\223\006\363").should == "some deflated text"
49
+ end
50
+ end
51
+
52
+ it "processes a successful result" do
53
+ res = mock("result")
54
+ res.stub!(:code).and_return("200")
55
+ res.stub!(:body).and_return('body')
56
+ res.stub!(:[]).with('content-encoding').and_return(nil)
57
+ @request.process_result(res).body.should == 'body'
58
+ @request.process_result(res).to_s.should == 'body'
59
+ end
60
+
61
+ it "doesn't classify successful requests as failed" do
62
+ 203.upto(206) do |code|
63
+ res = mock("result")
64
+ res.stub!(:code).and_return(code.to_s)
65
+ res.stub!(:body).and_return("")
66
+ res.stub!(:[]).with('content-encoding').and_return(nil)
67
+ @request.process_result(res).should be_empty
68
+ end
69
+ end
70
+
71
+ it "parses a url into a URI object" do
72
+ URI.should_receive(:parse).with('http://example.com/resource')
73
+ @request.parse_url('http://example.com/resource')
74
+ end
75
+
76
+ it "adds http:// to the front of resources specified in the syntax example.com/resource" do
77
+ URI.should_receive(:parse).with('http://example.com/resource')
78
+ @request.parse_url('example.com/resource')
79
+ end
80
+
81
+ describe "user - password" do
82
+ it "extracts the username and password when parsing http://user:password@example.com/" do
83
+ URI.stub!(:parse).and_return(mock('uri', :user => 'joe', :password => 'pass1'))
84
+ @request.parse_url_with_auth('http://joe:pass1@example.com/resource')
85
+ @request.user.should == 'joe'
86
+ @request.password.should == 'pass1'
87
+ end
88
+
89
+ it "doesn't overwrite user and password (which may have already been set by the Resource constructor) if there is no user/password in the url" do
90
+ URI.stub!(:parse).and_return(mock('uri', :user => nil, :password => nil))
91
+ @request = RestClient::Request.new(:method => 'get', :url => 'example.com', :user => 'beth', :password => 'pass2')
92
+ @request.parse_url_with_auth('http://example.com/resource')
93
+ @request.user.should == 'beth'
94
+ @request.password.should == 'pass2'
95
+ end
96
+ end
97
+
98
+ it "correctly formats cookies provided to the constructor" do
99
+ URI.stub!(:parse).and_return(mock('uri', :user => nil, :password => nil))
100
+ @request = RestClient::Request.new(:method => 'get', :url => 'example.com', :cookies => {:session_id => '1', :user_id => "someone" })
101
+ @request.should_receive(:default_headers).and_return({'foo' => 'bar'})
102
+ headers = @request.make_headers({}).should == { 'Foo' => 'bar', 'Cookie' => 'session_id=1,user_id=someone'}
103
+ end
104
+
105
+ it "determines the Net::HTTP class to instantiate by the method name" do
106
+ @request.net_http_request_class(:put).should == Net::HTTP::Put
107
+ end
108
+
109
+ describe "user headers" do
110
+ it "merges user headers with the default headers" do
111
+ @request.should_receive(:default_headers).and_return({ '1' => '2' })
112
+ headers = @request.make_headers('3' => '4')
113
+ headers.should have_key('1')
114
+ headers['1'].should == '2'
115
+ headers.should have_key('3')
116
+ headers['3'].should == '4'
117
+ end
118
+
119
+ it "prefers the user header when the same header exists in the defaults" do
120
+ @request.should_receive(:default_headers).and_return({ '1' => '2' })
121
+ headers = @request.make_headers('1' => '3')
122
+ headers.should have_key('1')
123
+ headers['1'].should == '3'
124
+ end
125
+ end
126
+
127
+ describe "header symbols" do
128
+
129
+ it "converts header symbols from :content_type to 'Content-type'" do
130
+ @request.should_receive(:default_headers).and_return({})
131
+ headers = @request.make_headers(:content_type => 'abc')
132
+ headers.should have_key('Content-type')
133
+ headers['Content-type'].should == 'abc'
134
+ end
135
+
136
+ it "converts content-type from extension to real content-type" do
137
+ @request.should_receive(:default_headers).and_return({})
138
+ headers = @request.make_headers(:content_type => 'json')
139
+ headers.should have_key('Content-type')
140
+ headers['Content-type'].should == 'application/json'
141
+ end
142
+
143
+ it "converts accept from extension(s) to real content-type(s)" do
144
+ @request.should_receive(:default_headers).and_return({})
145
+ headers = @request.make_headers(:accept => 'json, mp3')
146
+ headers.should have_key('Accept')
147
+ headers['Accept'].should == 'application/json, audio/mpeg'
148
+
149
+ @request.should_receive(:default_headers).and_return({})
150
+ headers = @request.make_headers(:accept => :json)
151
+ headers.should have_key('Accept')
152
+ headers['Accept'].should == 'application/json'
153
+ end
154
+
155
+ it "converts header values to strings" do
156
+ @request.make_headers('A' => 1)['A'].should == '1'
157
+ end
158
+ end
159
+
160
+ it "executes by constructing the Net::HTTP object, headers, and payload and calling transmit" do
161
+ @request.should_receive(:parse_url_with_auth).with('http://some/resource').and_return(@uri)
162
+ klass = mock("net:http class")
163
+ @request.should_receive(:net_http_request_class).with(:put).and_return(klass)
164
+ klass.should_receive(:new).and_return('result')
165
+ @request.should_receive(:transmit).with(@uri, 'result', kind_of(RestClient::Payload::Base))
166
+ @request.execute
167
+ end
168
+
169
+ it "transmits the request with Net::HTTP" do
170
+ @http.should_receive(:request).with('req', 'payload')
171
+ @request.should_receive(:process_result)
172
+ @request.transmit(@uri, 'req', 'payload')
173
+ end
174
+
175
+ describe "payload" do
176
+ it "sends nil payloads" do
177
+ @http.should_receive(:request).with('req', nil)
178
+ @request.should_receive(:process_result)
179
+ @request.stub!(:response_log)
180
+ @request.transmit(@uri, 'req', nil)
181
+ end
182
+
183
+ it "passes non-hash payloads straight through" do
184
+ @request.process_payload("x").should == "x"
185
+ end
186
+
187
+ it "converts a hash payload to urlencoded data" do
188
+ @request.process_payload(:a => 'b c+d').should == "a=b%20c%2Bd"
189
+ end
190
+
191
+ it "accepts nested hashes in payload" do
192
+ payload = @request.process_payload(:user => { :name => 'joe', :location => { :country => 'USA', :state => 'CA' }})
193
+ payload.should include('user[name]=joe')
194
+ payload.should include('user[location][country]=USA')
195
+ payload.should include('user[location][state]=CA')
196
+ end
197
+ end
198
+
199
+ it "set urlencoded content_type header on hash payloads" do
200
+ @request.process_payload(:a => 1)
201
+ @request.headers[:content_type].should == 'application/x-www-form-urlencoded'
202
+ end
203
+
204
+ describe "credentials" do
205
+ it "sets up the credentials prior to the request" do
206
+ @http.stub!(:request)
207
+ @request.stub!(:process_result)
208
+ @request.stub!(:response_log)
209
+
210
+ @request.stub!(:user).and_return('joe')
211
+ @request.stub!(:password).and_return('mypass')
212
+ @request.should_receive(:setup_credentials).with('req')
213
+
214
+ @request.transmit(@uri, 'req', nil)
215
+ end
216
+
217
+ it "does not attempt to send any credentials if user is nil" do
218
+ @request.stub!(:user).and_return(nil)
219
+ req = mock("request")
220
+ req.should_not_receive(:basic_auth)
221
+ @request.setup_credentials(req)
222
+ end
223
+
224
+ it "setup credentials when there's a user" do
225
+ @request.stub!(:user).and_return('joe')
226
+ @request.stub!(:password).and_return('mypass')
227
+ req = mock("request")
228
+ req.should_receive(:basic_auth).with('joe', 'mypass')
229
+ @request.setup_credentials(req)
230
+ end
231
+ end
232
+
233
+ it "catches EOFError and shows the more informative ServerBrokeConnection" do
234
+ @http.stub!(:request).and_raise(EOFError)
235
+ lambda { @request.transmit(@uri, 'req', nil) }.should raise_error(RestClient::ServerBrokeConnection)
236
+ end
237
+
238
+ it "class method execute wraps constructor" do
239
+ req = mock("rest request")
240
+ RestClient::Request.should_receive(:new).with(1 => 2).and_return(req)
241
+ req.should_receive(:execute)
242
+ RestClient::Request.execute(1 => 2)
243
+ end
244
+
245
+ describe "exception" do
246
+ it "raises Unauthorized when the response is 401" do
247
+ res = mock('response', :code => '401', :[] => ['content-encoding' => ''], :body => '' )
248
+ lambda { @request.process_result(res) }.should raise_error(RestClient::Unauthorized)
249
+ end
250
+
251
+ it "raises ResourceNotFound when the response is 404" do
252
+ res = mock('response', :code => '404', :[] => ['content-encoding' => ''], :body => '' )
253
+ lambda { @request.process_result(res) }.should raise_error(RestClient::ResourceNotFound)
254
+ end
255
+
256
+ it "raises RequestFailed otherwise" do
257
+ res = mock('response', :code => '500', :[] => ['content-encoding' => ''], :body => '' )
258
+ lambda { @request.process_result(res) }.should raise_error(RestClient::InternalServerError)
259
+ end
260
+ end
261
+
262
+ describe "block usage" do
263
+ it "returns what asked to" do
264
+ res = mock('response', :code => '401', :[] => ['content-encoding' => ''], :body => '' )
265
+ @request.process_result(res){|response| "foo"}.should == "foo"
266
+ end
267
+ end
268
+
269
+ describe "proxy" do
270
+ it "creates a proxy class if a proxy url is given" do
271
+ RestClient.stub!(:proxy).and_return("http://example.com/")
272
+ @request.net_http_class.should include(Net::HTTP::ProxyDelta)
273
+ end
274
+
275
+ it "creates a non-proxy class if a proxy url is not given" do
276
+ @request.net_http_class.should_not include(Net::HTTP::ProxyDelta)
277
+ end
278
+ end
279
+
280
+
281
+ describe "logging" do
282
+ it "logs a get request" do
283
+ log = RestClient.log = []
284
+ RestClient::Request.new(:method => :get, :url => 'http://url').log_request
285
+ ['RestClient.get "http://url", "Accept-encoding"=>"gzip, deflate", "Accept"=>"*/*; q=0.5, application/xml"' + "\n",
286
+ 'RestClient.get "http://url", "Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate"' + "\n"].should include(log[0])
287
+ end
288
+
289
+ it "logs a post request with a small payload" do
290
+ log = RestClient.log = []
291
+ RestClient::Request.new(:method => :post, :url => 'http://url', :payload => 'foo').log_request
292
+ ['RestClient.post "http://url", "foo", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"3", "Accept"=>"*/*; q=0.5, application/xml"' + "\n",
293
+ 'RestClient.post "http://url", "foo", "Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"3"' + "\n"].should include(log[0])
294
+ end
295
+
296
+ it "logs a post request with a large payload" do
297
+ log = RestClient.log = []
298
+ RestClient::Request.new(:method => :post, :url => 'http://url', :payload => ('x' * 1000)).log_request
299
+ ['RestClient.post "http://url", 1000 byte(s) length, "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000", "Accept"=>"*/*; q=0.5, application/xml"' + "\n",
300
+ 'RestClient.post "http://url", 1000 byte(s) length, "Accept"=>"*/*; q=0.5, application/xml", "Accept-encoding"=>"gzip, deflate", "Content-Length"=>"1000"' + "\n"].should include(log[0])
301
+ end
302
+
303
+ it "logs input headers as a hash" do
304
+ log = RestClient.log = []
305
+ RestClient::Request.new(:method => :get, :url => 'http://url', :headers => { :accept => 'text/plain' }).log_request
306
+ ['RestClient.get "http://url", "Accept-encoding"=>"gzip, deflate", "Accept"=>"text/plain"' + "\n",
307
+ 'RestClient.get "http://url", "Accept"=>"text/plain", "Accept-encoding"=>"gzip, deflate"' + "\n"].should include(log[0])
308
+ end
309
+
310
+ it "logs a response including the status code, content type, and result body size in bytes" do
311
+ log = RestClient.log = []
312
+ res = mock('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
313
+ res.stub!(:[]).with('Content-type').and_return('text/html')
314
+ @request.log_response res
315
+ log[0].should == "# => 200 OK | text/html 4 bytes\n"
316
+ end
317
+
318
+ it "logs a response with a nil Content-type" do
319
+ log = RestClient.log = []
320
+ res = mock('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
321
+ res.stub!(:[]).with('Content-type').and_return(nil)
322
+ @request.log_response res
323
+ log[0].should == "# => 200 OK | 4 bytes\n"
324
+ end
325
+
326
+ it "logs a response with a nil body" do
327
+ log = RestClient.log = []
328
+ res = mock('result', :code => '200', :class => Net::HTTPOK, :body => nil)
329
+ res.stub!(:[]).with('Content-type').and_return('text/html; charset=utf-8')
330
+ @request.log_response res
331
+ log[0].should == "# => 200 OK | text/html 0 bytes\n"
332
+ end
333
+ end
334
+
335
+ it "strips the charset from the response content type" do
336
+ log = RestClient.log = []
337
+ res = mock('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
338
+ res.stub!(:[]).with('Content-type').and_return('text/html; charset=utf-8')
339
+ @request.log_response res
340
+ log[0].should == "# => 200 OK | text/html 4 bytes\n"
341
+ end
342
+
343
+ describe "timeout" do
344
+ it "set read_timeout" do
345
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123)
346
+ @http.stub!(:request)
347
+ @request.stub!(:process_result)
348
+ @request.stub!(:response_log)
349
+
350
+ @net.should_receive(:read_timeout=).with(123)
351
+
352
+ @request.transmit(@uri, 'req', nil)
353
+ end
354
+
355
+ it "set open_timeout" do
356
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :open_timeout => 123)
357
+ @http.stub!(:request)
358
+ @request.stub!(:process_result)
359
+ @request.stub!(:response_log)
360
+
361
+ @net.should_receive(:open_timeout=).with(123)
362
+
363
+ @request.transmit(@uri, 'req', nil)
364
+ end
365
+ end
366
+
367
+ describe "ssl" do
368
+ it "uses SSL when the URI refers to a https address" do
369
+ @uri.stub!(:is_a?).with(URI::HTTPS).and_return(true)
370
+ @net.should_receive(:use_ssl=).with(true)
371
+ @http.stub!(:request)
372
+ @request.stub!(:process_result)
373
+ @request.stub!(:response_log)
374
+ @request.transmit(@uri, 'req', 'payload')
375
+ end
376
+
377
+ it "should default to not verifying ssl certificates" do
378
+ @request.verify_ssl.should == false
379
+ end
380
+
381
+ it "should set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is false" do
382
+ @net.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
383
+ @http.stub!(:request)
384
+ @request.stub!(:process_result)
385
+ @request.stub!(:response_log)
386
+ @request.transmit(@uri, 'req', 'payload')
387
+ end
388
+
389
+ it "should not set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is true" do
390
+ @request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload', :verify_ssl => true)
391
+ @net.should_not_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
392
+ @http.stub!(:request)
393
+ @request.stub!(:process_result)
394
+ @request.stub!(:response_log)
395
+ @request.transmit(@uri, 'req', 'payload')
396
+ end
397
+
398
+ it "should set net.verify_mode to the passed value if verify_ssl is an OpenSSL constant" do
399
+ mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
400
+ @request = RestClient::Request.new( :method => :put,
401
+ :url => 'https://some/resource',
402
+ :payload => 'payload',
403
+ :verify_ssl => mode )
404
+ @net.should_receive(:verify_mode=).with(mode)
405
+ @http.stub!(:request)
406
+ @request.stub!(:process_result)
407
+ @request.stub!(:response_log)
408
+ @request.transmit(@uri, 'req', 'payload')
409
+ end
410
+
411
+ it "should default to not having an ssl_client_cert" do
412
+ @request.ssl_client_cert.should be(nil)
413
+ end
414
+
415
+ it "should set the ssl_client_cert if provided" do
416
+ @request = RestClient::Request.new(
417
+ :method => :put,
418
+ :url => 'https://some/resource',
419
+ :payload => 'payload',
420
+ :ssl_client_cert => "whatsupdoc!"
421
+ )
422
+ @net.should_receive(:cert=).with("whatsupdoc!")
423
+ @http.stub!(:request)
424
+ @request.stub!(:process_result)
425
+ @request.stub!(:response_log)
426
+ @request.transmit(@uri, 'req', 'payload')
427
+ end
428
+
429
+ it "should not set the ssl_client_cert if it is not provided" do
430
+ @request = RestClient::Request.new(
431
+ :method => :put,
432
+ :url => 'https://some/resource',
433
+ :payload => 'payload'
434
+ )
435
+ @net.should_not_receive(:cert=).with("whatsupdoc!")
436
+ @http.stub!(:request)
437
+ @request.stub!(:process_result)
438
+ @request.stub!(:response_log)
439
+ @request.transmit(@uri, 'req', 'payload')
440
+ end
441
+
442
+ it "should default to not having an ssl_client_key" do
443
+ @request.ssl_client_key.should be(nil)
444
+ end
445
+
446
+ it "should set the ssl_client_key if provided" do
447
+ @request = RestClient::Request.new(
448
+ :method => :put,
449
+ :url => 'https://some/resource',
450
+ :payload => 'payload',
451
+ :ssl_client_key => "whatsupdoc!"
452
+ )
453
+ @net.should_receive(:key=).with("whatsupdoc!")
454
+ @http.stub!(:request)
455
+ @request.stub!(:process_result)
456
+ @request.stub!(:response_log)
457
+ @request.transmit(@uri, 'req', 'payload')
458
+ end
459
+
460
+ it "should not set the ssl_client_key if it is not provided" do
461
+ @request = RestClient::Request.new(
462
+ :method => :put,
463
+ :url => 'https://some/resource',
464
+ :payload => 'payload'
465
+ )
466
+ @net.should_not_receive(:key=).with("whatsupdoc!")
467
+ @http.stub!(:request)
468
+ @request.stub!(:process_result)
469
+ @request.stub!(:response_log)
470
+ @request.transmit(@uri, 'req', 'payload')
471
+ end
472
+
473
+ it "should default to not having an ssl_ca_file" do
474
+ @request.ssl_ca_file.should be(nil)
475
+ end
476
+
477
+ it "should set the ssl_ca_file if provided" do
478
+ @request = RestClient::Request.new(
479
+ :method => :put,
480
+ :url => 'https://some/resource',
481
+ :payload => 'payload',
482
+ :ssl_ca_file => "Certificate Authority File"
483
+ )
484
+ @net.should_receive(:ca_file=).with("Certificate Authority File")
485
+ @http.stub!(:request)
486
+ @request.stub!(:process_result)
487
+ @request.stub!(:response_log)
488
+ @request.transmit(@uri, 'req', 'payload')
489
+ end
490
+
491
+ it "should not set the ssl_ca_file if it is not provided" do
492
+ @request = RestClient::Request.new(
493
+ :method => :put,
494
+ :url => 'https://some/resource',
495
+ :payload => 'payload'
496
+ )
497
+ @net.should_not_receive(:ca_file=).with("Certificate Authority File")
498
+ @http.stub!(:request)
499
+ @request.stub!(:process_result)
500
+ @request.stub!(:response_log)
501
+ @request.transmit(@uri, 'req', 'payload')
502
+ end
503
+ end
504
+
505
+ it "should still return a response object for 204 No Content responses" do
506
+ @request = RestClient::Request.new(
507
+ :method => :put,
508
+ :url => 'https://some/resource',
509
+ :payload => 'payload'
510
+ )
511
+ net_http_res = Net::HTTPNoContent.new("", "204", "No Content")
512
+ net_http_res.stub!(:read_body).and_return(nil)
513
+ @http.should_receive(:request).and_return(@request.fetch_body(net_http_res))
514
+ response = @request.transmit(@uri, 'req', 'payload')
515
+ response.should_not be_nil
516
+ response.code.should equal(204)
517
+ end
518
+ end