rest-client 1.7.0.rc1-x86-mingw32

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.

Potentially problematic release.


This version of rest-client might be problematic. Click here for more details.

Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +14 -0
  5. data/AUTHORS +81 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE +21 -0
  8. data/README.rdoc +325 -0
  9. data/Rakefile +117 -0
  10. data/bin/restclient +93 -0
  11. data/history.md +166 -0
  12. data/lib/rest-client.rb +2 -0
  13. data/lib/rest_client.rb +2 -0
  14. data/lib/restclient.rb +164 -0
  15. data/lib/restclient/abstract_response.rb +106 -0
  16. data/lib/restclient/exceptions.rb +203 -0
  17. data/lib/restclient/payload.rb +240 -0
  18. data/lib/restclient/platform.rb +30 -0
  19. data/lib/restclient/raw_response.rb +34 -0
  20. data/lib/restclient/request.rb +582 -0
  21. data/lib/restclient/resource.rb +169 -0
  22. data/lib/restclient/response.rb +24 -0
  23. data/lib/restclient/version.rb +7 -0
  24. data/lib/restclient/windows.rb +8 -0
  25. data/lib/restclient/windows/root_certs.rb +105 -0
  26. data/rest-client.gemspec +30 -0
  27. data/rest-client.windows.gemspec +19 -0
  28. data/spec/integration/capath_digicert/244b5494.0 +19 -0
  29. data/spec/integration/capath_digicert/81b9768f.0 +19 -0
  30. data/spec/integration/capath_digicert/README +8 -0
  31. data/spec/integration/capath_digicert/digicert.crt +19 -0
  32. data/spec/integration/capath_verisign/415660c1.0 +14 -0
  33. data/spec/integration/capath_verisign/7651b327.0 +14 -0
  34. data/spec/integration/capath_verisign/README +8 -0
  35. data/spec/integration/capath_verisign/verisign.crt +14 -0
  36. data/spec/integration/certs/digicert.crt +19 -0
  37. data/spec/integration/certs/verisign.crt +14 -0
  38. data/spec/integration/integration_spec.rb +35 -0
  39. data/spec/integration/request_spec.rb +104 -0
  40. data/spec/spec_helper.rb +12 -0
  41. data/spec/unit/abstract_response_spec.rb +85 -0
  42. data/spec/unit/exceptions_spec.rb +95 -0
  43. data/spec/unit/master_shake.jpg +0 -0
  44. data/spec/unit/payload_spec.rb +245 -0
  45. data/spec/unit/raw_response_spec.rb +17 -0
  46. data/spec/unit/request2_spec.rb +32 -0
  47. data/spec/unit/request_spec.rb +905 -0
  48. data/spec/unit/resource_spec.rb +133 -0
  49. data/spec/unit/response_spec.rb +166 -0
  50. data/spec/unit/restclient_spec.rb +79 -0
  51. data/spec/unit/windows/root_certs_spec.rb +22 -0
  52. metadata +241 -0
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe RestClient::RawResponse do
4
+ before do
5
+ @tf = double("Tempfile", :read => "the answer is 42", :open => true)
6
+ @net_http_res = double('net http response')
7
+ @response = RestClient::RawResponse.new(@tf, @net_http_res, {})
8
+ end
9
+
10
+ it "behaves like string" do
11
+ @response.to_s.should eq 'the answer is 42'
12
+ end
13
+
14
+ it "exposes a Tempfile" do
15
+ @response.file.should eq @tf
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe RestClient::Request do
4
+
5
+ it "manage params for get requests" do
6
+ stub_request(:get, 'http://some/resource?a=b&c=d').with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Foo'=>'bar'}).to_return(:body => 'foo', :status => 200)
7
+ RestClient::Request.execute(:url => 'http://some/resource', :method => :get, :headers => {:foo => :bar, :params => {:a => :b, 'c' => 'd'}}).body.should eq 'foo'
8
+
9
+ stub_request(:get, 'http://some/resource').with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Foo'=>'bar', 'params' => 'a'}).to_return(:body => 'foo', :status => 200)
10
+ RestClient::Request.execute(:url => 'http://some/resource', :method => :get, :headers => {:foo => :bar, :params => :a}).body.should eq 'foo'
11
+ end
12
+
13
+ it "can use a block to process response" do
14
+ response_value = nil
15
+ block = Proc.new do |http_response|
16
+ response_value = http_response.body
17
+ end
18
+ stub_request(:get, 'http://some/resource?a=b&c=d').with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Foo'=>'bar'}).to_return(:body => 'foo', :status => 200)
19
+ RestClient::Request.execute(:url => 'http://some/resource', :method => :get, :headers => {:foo => :bar, :params => {:a => :b, 'c' => 'd'}}, :block_response => block)
20
+ response_value.should eq "foo"
21
+ end
22
+
23
+ it 'closes payload if not nil' do
24
+ test_file = File.new(File.join( File.dirname(File.expand_path(__FILE__)), 'master_shake.jpg'))
25
+
26
+ stub_request(:post, 'http://some/resource').with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate'}).to_return(:body => 'foo', :status => 200)
27
+ RestClient::Request.execute(:url => 'http://some/resource', :method => :post, :payload => {:file => test_file})
28
+
29
+ test_file.closed?.should be_true
30
+ end
31
+
32
+ end
@@ -0,0 +1,905 @@
1
+ require 'spec_helper'
2
+
3
+ describe RestClient::Request do
4
+ before do
5
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
6
+
7
+ @uri = double("uri")
8
+ @uri.stub(:request_uri).and_return('/resource')
9
+ @uri.stub(:host).and_return('some')
10
+ @uri.stub(:port).and_return(80)
11
+
12
+ @net = double("net::http base")
13
+ @http = double("net::http connection")
14
+ Net::HTTP.stub(:new).and_return(@net)
15
+ @net.stub(:start).and_yield(@http)
16
+ @net.stub(:use_ssl=)
17
+ @net.stub(:verify_mode=)
18
+ @net.stub(:verify_callback=)
19
+ allow(@net).to receive(:ciphers=)
20
+ allow(@net).to receive(:cert_store=)
21
+ RestClient.log = nil
22
+ end
23
+
24
+ it "accept */* mimetype, preferring xml" do
25
+ @request.default_headers[:accept].should eq '*/*; 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 eq '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 eq "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 eq "some deflated text"
49
+ end
50
+ end
51
+
52
+ it "processes a successful result" do
53
+ res = double("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 eq 'body'
58
+ @request.process_result(res).to_s.should eq 'body'
59
+ end
60
+
61
+ it "doesn't classify successful requests as failed" do
62
+ 203.upto(207) do |code|
63
+ res = double("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(double('uri', :user => 'joe', :password => 'pass1'))
84
+ @request.parse_url_with_auth('http://joe:pass1@example.com/resource')
85
+ @request.user.should eq 'joe'
86
+ @request.password.should eq 'pass1'
87
+ end
88
+
89
+ it "extracts with escaping the username and password when parsing http://user:password@example.com/" do
90
+ URI.stub(:parse).and_return(double('uri', :user => 'joe%20', :password => 'pass1'))
91
+ @request.parse_url_with_auth('http://joe%20:pass1@example.com/resource')
92
+ @request.user.should eq 'joe '
93
+ @request.password.should eq 'pass1'
94
+ end
95
+
96
+ 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
97
+ URI.stub(:parse).and_return(double('uri', :user => nil, :password => nil))
98
+ @request = RestClient::Request.new(:method => 'get', :url => 'example.com', :user => 'beth', :password => 'pass2')
99
+ @request.parse_url_with_auth('http://example.com/resource')
100
+ @request.user.should eq 'beth'
101
+ @request.password.should eq 'pass2'
102
+ end
103
+ end
104
+
105
+ it "correctly formats cookies provided to the constructor" do
106
+ URI.stub(:parse).and_return(double('uri', :user => nil, :password => nil))
107
+ @request = RestClient::Request.new(:method => 'get', :url => 'example.com', :cookies => {:session_id => '1', :user_id => "someone" })
108
+ @request.should_receive(:default_headers).and_return({'Foo' => 'bar'})
109
+ @request.make_headers({}).should eq({ 'Foo' => 'bar', 'Cookie' => 'session_id=1; user_id=someone'})
110
+ end
111
+
112
+ it "does not escape or unescape cookies" do
113
+ cookie = 'Foo%20:Bar%0A~'
114
+ @request = RestClient::Request.new(:method => 'get', :url => 'example.com',
115
+ :cookies => {:test => cookie})
116
+ @request.should_receive(:default_headers).and_return({'Foo' => 'bar'})
117
+ @request.make_headers({}).should eq({
118
+ 'Foo' => 'bar',
119
+ 'Cookie' => "test=#{cookie}"
120
+ })
121
+ end
122
+
123
+ it "rejects cookie names containing invalid characters" do
124
+ # Cookie validity is something of a mess, but we should reject the worst of
125
+ # the RFC 6265 (4.1.1) prohibited characters such as control characters.
126
+
127
+ ['', 'foo=bar', 'foo;bar', "foo\nbar"].each do |cookie_name|
128
+ lambda {
129
+ RestClient::Request.new(:method => 'get', :url => 'example.com',
130
+ :cookies => {cookie_name => 'value'})
131
+ }.should raise_error(ArgumentError, /\AInvalid cookie name/)
132
+ end
133
+ end
134
+
135
+ it "rejects cookie values containing invalid characters" do
136
+ # Cookie validity is something of a mess, but we should reject the worst of
137
+ # the RFC 6265 (4.1.1) prohibited characters such as control characters.
138
+
139
+ ['foo,bar', 'foo;bar', "foo\nbar"].each do |cookie_value|
140
+ lambda {
141
+ RestClient::Request.new(:method => 'get', :url => 'example.com',
142
+ :cookies => {'test' => cookie_value})
143
+ }.should raise_error(ArgumentError, /\AInvalid cookie value/)
144
+ end
145
+ end
146
+
147
+ it "uses netrc credentials" do
148
+ URI.stub(:parse).and_return(double('uri', :user => nil, :password => nil, :host => 'example.com'))
149
+ Netrc.stub(:read).and_return('example.com' => ['a', 'b'])
150
+ @request.parse_url_with_auth('http://example.com/resource')
151
+ @request.user.should eq 'a'
152
+ @request.password.should eq 'b'
153
+ end
154
+
155
+ it "uses credentials in the url in preference to netrc" do
156
+ URI.stub(:parse).and_return(double('uri', :user => 'joe%20', :password => 'pass1', :host => 'example.com'))
157
+ Netrc.stub(:read).and_return('example.com' => ['a', 'b'])
158
+ @request.parse_url_with_auth('http://joe%20:pass1@example.com/resource')
159
+ @request.user.should eq 'joe '
160
+ @request.password.should eq 'pass1'
161
+ end
162
+
163
+ it "determines the Net::HTTP class to instantiate by the method name" do
164
+ @request.net_http_request_class(:put).should eq Net::HTTP::Put
165
+ end
166
+
167
+ describe "user headers" do
168
+ it "merges user headers with the default headers" do
169
+ @request.should_receive(:default_headers).and_return({ :accept => '*/*; q=0.5, application/xml', :accept_encoding => 'gzip, deflate' })
170
+ headers = @request.make_headers("Accept" => "application/json", :accept_encoding => 'gzip')
171
+ headers.should have_key "Accept-Encoding"
172
+ headers["Accept-Encoding"].should eq "gzip"
173
+ headers.should have_key "Accept"
174
+ headers["Accept"].should eq "application/json"
175
+ end
176
+
177
+ it "prefers the user header when the same header exists in the defaults" do
178
+ @request.should_receive(:default_headers).and_return({ '1' => '2' })
179
+ headers = @request.make_headers('1' => '3')
180
+ headers.should have_key('1')
181
+ headers['1'].should eq '3'
182
+ end
183
+
184
+ it "converts user headers to string before calling CGI::unescape which fails on non string values" do
185
+ @request.should_receive(:default_headers).and_return({ '1' => '2' })
186
+ headers = @request.make_headers('1' => 3)
187
+ headers.should have_key('1')
188
+ headers['1'].should eq '3'
189
+ end
190
+ end
191
+
192
+ describe "header symbols" do
193
+
194
+ it "converts header symbols from :content_type to 'Content-Type'" do
195
+ @request.should_receive(:default_headers).and_return({})
196
+ headers = @request.make_headers(:content_type => 'abc')
197
+ headers.should have_key('Content-Type')
198
+ headers['Content-Type'].should eq 'abc'
199
+ end
200
+
201
+ it "converts content-type from extension to real content-type" do
202
+ @request.should_receive(:default_headers).and_return({})
203
+ headers = @request.make_headers(:content_type => 'json')
204
+ headers.should have_key('Content-Type')
205
+ headers['Content-Type'].should eq 'application/json'
206
+ end
207
+
208
+ it "converts accept from extension(s) to real content-type(s)" do
209
+ @request.should_receive(:default_headers).and_return({})
210
+ headers = @request.make_headers(:accept => 'json, mp3')
211
+ headers.should have_key('Accept')
212
+ headers['Accept'].should eq 'application/json, audio/mpeg'
213
+
214
+ @request.should_receive(:default_headers).and_return({})
215
+ headers = @request.make_headers(:accept => :json)
216
+ headers.should have_key('Accept')
217
+ headers['Accept'].should eq 'application/json'
218
+ end
219
+
220
+ it "only convert symbols in header" do
221
+ @request.should_receive(:default_headers).and_return({})
222
+ headers = @request.make_headers({:foo_bar => 'value', "bar_bar" => 'value'})
223
+ headers['Foo-Bar'].should eq 'value'
224
+ headers['bar_bar'].should eq 'value'
225
+ end
226
+
227
+ it "converts header values to strings" do
228
+ @request.make_headers('A' => 1)['A'].should eq '1'
229
+ end
230
+ end
231
+
232
+ it "executes by constructing the Net::HTTP object, headers, and payload and calling transmit" do
233
+ @request.should_receive(:parse_url_with_auth).with('http://some/resource').and_return(@uri)
234
+ klass = double("net:http class")
235
+ @request.should_receive(:net_http_request_class).with(:put).and_return(klass)
236
+ klass.should_receive(:new).and_return('result')
237
+ @request.should_receive(:transmit).with(@uri, 'result', kind_of(RestClient::Payload::Base))
238
+ @request.execute
239
+ end
240
+
241
+ it "transmits the request with Net::HTTP" do
242
+ @http.should_receive(:request).with('req', 'payload')
243
+ @request.should_receive(:process_result)
244
+ @request.transmit(@uri, 'req', 'payload')
245
+ end
246
+
247
+ describe "payload" do
248
+ it "sends nil payloads" do
249
+ @http.should_receive(:request).with('req', nil)
250
+ @request.should_receive(:process_result)
251
+ @request.stub(:response_log)
252
+ @request.transmit(@uri, 'req', nil)
253
+ end
254
+
255
+ it "passes non-hash payloads straight through" do
256
+ @request.process_payload("x").should eq "x"
257
+ end
258
+
259
+ it "converts a hash payload to urlencoded data" do
260
+ @request.process_payload(:a => 'b c+d').should eq "a=b%20c%2Bd"
261
+ end
262
+
263
+ it "accepts nested hashes in payload" do
264
+ payload = @request.process_payload(:user => { :name => 'joe', :location => { :country => 'USA', :state => 'CA' }})
265
+ payload.should include('user[name]=joe')
266
+ payload.should include('user[location][country]=USA')
267
+ payload.should include('user[location][state]=CA')
268
+ end
269
+ end
270
+
271
+ it "set urlencoded content_type header on hash payloads" do
272
+ @request.process_payload(:a => 1)
273
+ @request.headers[:content_type].should eq 'application/x-www-form-urlencoded'
274
+ end
275
+
276
+ describe "credentials" do
277
+ it "sets up the credentials prior to the request" do
278
+ @http.stub(:request)
279
+
280
+ @request.stub(:process_result)
281
+ @request.stub(:response_log)
282
+
283
+ @request.stub(:user).and_return('joe')
284
+ @request.stub(:password).and_return('mypass')
285
+ @request.should_receive(:setup_credentials).with('req')
286
+
287
+ @request.transmit(@uri, 'req', nil)
288
+ end
289
+
290
+ it "does not attempt to send any credentials if user is nil" do
291
+ @request.stub(:user).and_return(nil)
292
+ req = double("request")
293
+ req.should_not_receive(:basic_auth)
294
+ @request.setup_credentials(req)
295
+ end
296
+
297
+ it "setup credentials when there's a user" do
298
+ @request.stub(:user).and_return('joe')
299
+ @request.stub(:password).and_return('mypass')
300
+ req = double("request")
301
+ req.should_receive(:basic_auth).with('joe', 'mypass')
302
+ @request.setup_credentials(req)
303
+ end
304
+ end
305
+
306
+ it "catches EOFError and shows the more informative ServerBrokeConnection" do
307
+ @http.stub(:request).and_raise(EOFError)
308
+ lambda { @request.transmit(@uri, 'req', nil) }.should raise_error(RestClient::ServerBrokeConnection)
309
+ end
310
+
311
+ it "catches OpenSSL::SSL::SSLError and raise it back without more informative message" do
312
+ @http.stub(:request).and_raise(OpenSSL::SSL::SSLError)
313
+ lambda { @request.transmit(@uri, 'req', nil) }.should raise_error(OpenSSL::SSL::SSLError)
314
+ end
315
+
316
+ it "catches Timeout::Error and raise the more informative RequestTimeout" do
317
+ @http.stub(:request).and_raise(Timeout::Error)
318
+ lambda { @request.transmit(@uri, 'req', nil) }.should raise_error(RestClient::RequestTimeout)
319
+ end
320
+
321
+ it "catches Timeout::Error and raise the more informative RequestTimeout" do
322
+ @http.stub(:request).and_raise(Errno::ETIMEDOUT)
323
+ lambda { @request.transmit(@uri, 'req', nil) }.should raise_error(RestClient::RequestTimeout)
324
+ end
325
+
326
+ it "class method execute wraps constructor" do
327
+ req = double("rest request")
328
+ RestClient::Request.should_receive(:new).with(1 => 2).and_return(req)
329
+ req.should_receive(:execute)
330
+ RestClient::Request.execute(1 => 2)
331
+ end
332
+
333
+ describe "exception" do
334
+ it "raises Unauthorized when the response is 401" do
335
+ res = double('response', :code => '401', :[] => ['content-encoding' => ''], :body => '' )
336
+ lambda { @request.process_result(res) }.should raise_error(RestClient::Unauthorized)
337
+ end
338
+
339
+ it "raises ResourceNotFound when the response is 404" do
340
+ res = double('response', :code => '404', :[] => ['content-encoding' => ''], :body => '' )
341
+ lambda { @request.process_result(res) }.should raise_error(RestClient::ResourceNotFound)
342
+ end
343
+
344
+ it "raises RequestFailed otherwise" do
345
+ res = double('response', :code => '500', :[] => ['content-encoding' => ''], :body => '' )
346
+ lambda { @request.process_result(res) }.should raise_error(RestClient::InternalServerError)
347
+ end
348
+ end
349
+
350
+ describe "block usage" do
351
+ it "returns what asked to" do
352
+ res = double('response', :code => '401', :[] => ['content-encoding' => ''], :body => '' )
353
+ @request.process_result(res){|response, request| "foo"}.should eq "foo"
354
+ end
355
+ end
356
+
357
+ describe "proxy" do
358
+ it "creates a proxy class if a proxy url is given" do
359
+ RestClient.stub(:proxy).and_return("http://example.com/")
360
+ @request.net_http_class.proxy_class?.should be_true
361
+ end
362
+
363
+ it "creates a non-proxy class if a proxy url is not given" do
364
+ @request.net_http_class.proxy_class?.should be_false
365
+ end
366
+ end
367
+
368
+
369
+ describe "logging" do
370
+ it "logs a get request" do
371
+ log = RestClient.log = []
372
+ RestClient::Request.new(:method => :get, :url => 'http://url').log_request
373
+ log[0].should eq %Q{RestClient.get "http://url", "Accept"=>"*/*; q=0.5, application/xml", "Accept-Encoding"=>"gzip, deflate"\n}
374
+ end
375
+
376
+ it "logs a post request with a small payload" do
377
+ log = RestClient.log = []
378
+ RestClient::Request.new(:method => :post, :url => 'http://url', :payload => 'foo').log_request
379
+ log[0].should eq %Q{RestClient.post "http://url", "foo", "Accept"=>"*/*; q=0.5, application/xml", "Accept-Encoding"=>"gzip, deflate", "Content-Length"=>"3"\n}
380
+ end
381
+
382
+ it "logs a post request with a large payload" do
383
+ log = RestClient.log = []
384
+ RestClient::Request.new(:method => :post, :url => 'http://url', :payload => ('x' * 1000)).log_request
385
+ log[0].should eq %Q{RestClient.post "http://url", 1000 byte(s) length, "Accept"=>"*/*; q=0.5, application/xml", "Accept-Encoding"=>"gzip, deflate", "Content-Length"=>"1000"\n}
386
+ end
387
+
388
+ it "logs input headers as a hash" do
389
+ log = RestClient.log = []
390
+ RestClient::Request.new(:method => :get, :url => 'http://url', :headers => { :accept => 'text/plain' }).log_request
391
+ log[0].should eq %Q{RestClient.get "http://url", "Accept"=>"text/plain", "Accept-Encoding"=>"gzip, deflate"\n}
392
+ end
393
+
394
+ it "logs a response including the status code, content type, and result body size in bytes" do
395
+ log = RestClient.log = []
396
+ res = double('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
397
+ res.stub(:[]).with('Content-type').and_return('text/html')
398
+ @request.log_response res
399
+ log[0].should eq "# => 200 OK | text/html 4 bytes\n"
400
+ end
401
+
402
+ it "logs a response with a nil Content-type" do
403
+ log = RestClient.log = []
404
+ res = double('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
405
+ res.stub(:[]).with('Content-type').and_return(nil)
406
+ @request.log_response res
407
+ log[0].should eq "# => 200 OK | 4 bytes\n"
408
+ end
409
+
410
+ it "logs a response with a nil body" do
411
+ log = RestClient.log = []
412
+ res = double('result', :code => '200', :class => Net::HTTPOK, :body => nil)
413
+ res.stub(:[]).with('Content-type').and_return('text/html; charset=utf-8')
414
+ @request.log_response res
415
+ log[0].should eq "# => 200 OK | text/html 0 bytes\n"
416
+ end
417
+ end
418
+
419
+ it "strips the charset from the response content type" do
420
+ log = RestClient.log = []
421
+ res = double('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
422
+ res.stub(:[]).with('Content-type').and_return('text/html; charset=utf-8')
423
+ @request.log_response res
424
+ log[0].should eq "# => 200 OK | text/html 4 bytes\n"
425
+ end
426
+
427
+ describe "timeout" do
428
+ it "does not set timeouts if not specified" do
429
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
430
+ @http.stub(:request)
431
+ @request.stub(:process_result)
432
+ @request.stub(:response_log)
433
+
434
+ @net.should_not_receive(:read_timeout=)
435
+ @net.should_not_receive(:open_timeout=)
436
+
437
+ @request.transmit(@uri, 'req', nil)
438
+ end
439
+
440
+ it "set read_timeout" do
441
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123)
442
+ @http.stub(:request)
443
+ @request.stub(:process_result)
444
+ @request.stub(:response_log)
445
+
446
+ @net.should_receive(:read_timeout=).with(123)
447
+
448
+ @request.transmit(@uri, 'req', nil)
449
+ end
450
+
451
+ it "set open_timeout" do
452
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :open_timeout => 123)
453
+ @http.stub(:request)
454
+ @request.stub(:process_result)
455
+ @request.stub(:response_log)
456
+
457
+ @net.should_receive(:open_timeout=).with(123)
458
+
459
+ @request.transmit(@uri, 'req', nil)
460
+ end
461
+
462
+ it "disable timeout by setting it to nil" do
463
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => nil, :open_timeout => nil)
464
+ @http.stub(:request)
465
+ @request.stub(:process_result)
466
+ @request.stub(:response_log)
467
+
468
+ @net.should_receive(:read_timeout=).with(nil)
469
+ @net.should_receive(:open_timeout=).with(nil)
470
+
471
+ @request.transmit(@uri, 'req', nil)
472
+ end
473
+
474
+ it "deprecated: disable timeout by setting it to -1" do
475
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => -1, :open_timeout => -1)
476
+ @http.stub(:request)
477
+ @request.stub(:process_result)
478
+ @request.stub(:response_log)
479
+
480
+ @request.should_receive(:warn)
481
+ @net.should_receive(:read_timeout=).with(nil)
482
+
483
+ @request.should_receive(:warn)
484
+ @net.should_receive(:open_timeout=).with(nil)
485
+
486
+ @request.transmit(@uri, 'req', nil)
487
+ end
488
+ end
489
+
490
+ describe "ssl" do
491
+ it "uses SSL when the URI refers to a https address" do
492
+ @uri.stub(:is_a?).with(URI::HTTPS).and_return(true)
493
+ @net.should_receive(:use_ssl=).with(true)
494
+ @http.stub(:request)
495
+ @request.stub(:process_result)
496
+ @request.stub(:response_log)
497
+ @request.transmit(@uri, 'req', 'payload')
498
+ end
499
+
500
+ it "should default to verifying ssl certificates" do
501
+ @request.verify_ssl.should eq OpenSSL::SSL::VERIFY_PEER
502
+ end
503
+
504
+ it "should have expected values for VERIFY_PEER and VERIFY_NONE" do
505
+ OpenSSL::SSL::VERIFY_NONE.should eq(0)
506
+ OpenSSL::SSL::VERIFY_PEER.should eq(1)
507
+ end
508
+
509
+ it "should set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is false" do
510
+ @request = RestClient::Request.new(:method => :put, :verify_ssl => false, :url => 'http://some/resource', :payload => 'payload')
511
+ @net.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
512
+ @http.stub(:request)
513
+ @request.stub(:process_result)
514
+ @request.stub(:response_log)
515
+ @request.transmit(@uri, 'req', 'payload')
516
+ end
517
+
518
+ it "should not set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is true" do
519
+ @request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload', :verify_ssl => true)
520
+ @net.should_not_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
521
+ @http.stub(:request)
522
+ @request.stub(:process_result)
523
+ @request.stub(:response_log)
524
+ @request.transmit(@uri, 'req', 'payload')
525
+ end
526
+
527
+ it "should set net.verify_mode to OpenSSL::SSL::VERIFY_PEER if verify_ssl is true" do
528
+ @request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload', :verify_ssl => true)
529
+ @net.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
530
+ @http.stub(:request)
531
+ @request.stub(:process_result)
532
+ @request.stub(:response_log)
533
+ @request.transmit(@uri, 'req', 'payload')
534
+ end
535
+
536
+ it "should set net.verify_mode to OpenSSL::SSL::VERIFY_PEER if verify_ssl is not given" do
537
+ @request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload')
538
+ @net.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
539
+ @http.stub(:request)
540
+ @request.stub(:process_result)
541
+ @request.stub(:response_log)
542
+ @request.transmit(@uri, 'req', 'payload')
543
+ end
544
+
545
+ it "should set net.verify_mode to the passed value if verify_ssl is an OpenSSL constant" do
546
+ mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
547
+ @request = RestClient::Request.new( :method => :put,
548
+ :url => 'https://some/resource',
549
+ :payload => 'payload',
550
+ :verify_ssl => mode )
551
+ @net.should_receive(:verify_mode=).with(mode)
552
+ @http.stub(:request)
553
+ @request.stub(:process_result)
554
+ @request.stub(:response_log)
555
+ @request.transmit(@uri, 'req', 'payload')
556
+ end
557
+
558
+ it "should default to not having an ssl_client_cert" do
559
+ @request.ssl_client_cert.should be(nil)
560
+ end
561
+
562
+ it "should set the ssl_version if provided" do
563
+ @request = RestClient::Request.new(
564
+ :method => :put,
565
+ :url => 'https://some/resource',
566
+ :payload => 'payload',
567
+ :ssl_version => "TLSv1"
568
+ )
569
+ @net.should_receive(:ssl_version=).with("TLSv1")
570
+ @http.stub(:request)
571
+ @request.stub(:process_result)
572
+ @request.stub(:response_log)
573
+ @request.transmit(@uri, 'req', 'payload')
574
+ end
575
+
576
+ it "should not set the ssl_version if not provided" do
577
+ @request = RestClient::Request.new(
578
+ :method => :put,
579
+ :url => 'https://some/resource',
580
+ :payload => 'payload'
581
+ )
582
+ @net.should_not_receive(:ssl_version=).with("TLSv1")
583
+ @http.stub(:request)
584
+ @request.stub(:process_result)
585
+ @request.stub(:response_log)
586
+ @request.transmit(@uri, 'req', 'payload')
587
+ end
588
+
589
+ it "should set the ssl_ciphers if provided" do
590
+ ciphers = 'AESGCM:HIGH:!aNULL:!eNULL:RC4+RSA'
591
+ @request = RestClient::Request.new(
592
+ :method => :put,
593
+ :url => 'https://some/resource',
594
+ :payload => 'payload',
595
+ :ssl_ciphers => ciphers
596
+ )
597
+ @net.should_receive(:ciphers=).with(ciphers)
598
+ @http.stub(:request)
599
+ @request.stub(:process_result)
600
+ @request.stub(:response_log)
601
+ @request.transmit(@uri, 'req', 'payload')
602
+ end
603
+
604
+ it "should not set the ssl_ciphers if set to nil" do
605
+ @request = RestClient::Request.new(
606
+ :method => :put,
607
+ :url => 'https://some/resource',
608
+ :payload => 'payload',
609
+ :ssl_ciphers => nil,
610
+ )
611
+ @net.should_not_receive(:ciphers=)
612
+ @http.stub(:request)
613
+ @request.stub(:process_result)
614
+ @request.stub(:response_log)
615
+ @request.transmit(@uri, 'req', 'payload')
616
+ end
617
+
618
+ it "should override ssl_ciphers with better defaults with weak default ciphers" do
619
+ stub_const(
620
+ '::OpenSSL::SSL::SSLContext::DEFAULT_PARAMS',
621
+ {
622
+ :ssl_version=>"SSLv23",
623
+ :verify_mode=>1,
624
+ :ciphers=>"ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
625
+ :options=>-2147480577,
626
+ }
627
+ )
628
+
629
+ @request = RestClient::Request.new(
630
+ :method => :put,
631
+ :url => 'https://some/resource',
632
+ :payload => 'payload',
633
+ )
634
+
635
+ @net.should_receive(:ciphers=).with(RestClient::Request::DefaultCiphers)
636
+
637
+ @http.stub(:request)
638
+ @request.stub(:process_result)
639
+ @request.stub(:response_log)
640
+ @request.transmit(@uri, 'req', 'payload')
641
+ end
642
+
643
+ it "should not override ssl_ciphers with better defaults with different default ciphers" do
644
+ stub_const(
645
+ '::OpenSSL::SSL::SSLContext::DEFAULT_PARAMS',
646
+ {
647
+ :ssl_version=>"SSLv23",
648
+ :verify_mode=>1,
649
+ :ciphers=>"HIGH:!aNULL:!eNULL:!EXPORT:!LOW:!MEDIUM:!SSLv2",
650
+ :options=>-2147480577,
651
+ }
652
+ )
653
+
654
+ @request = RestClient::Request.new(
655
+ :method => :put,
656
+ :url => 'https://some/resource',
657
+ :payload => 'payload',
658
+ )
659
+
660
+ @net.should_not_receive(:ciphers=)
661
+
662
+ @http.stub(:request)
663
+ @request.stub(:process_result)
664
+ @request.stub(:response_log)
665
+ @request.transmit(@uri, 'req', 'payload')
666
+ end
667
+
668
+ it "should set the ssl_client_cert if provided" do
669
+ @request = RestClient::Request.new(
670
+ :method => :put,
671
+ :url => 'https://some/resource',
672
+ :payload => 'payload',
673
+ :ssl_client_cert => "whatsupdoc!"
674
+ )
675
+ @net.should_receive(:cert=).with("whatsupdoc!")
676
+ @http.stub(:request)
677
+ @request.stub(:process_result)
678
+ @request.stub(:response_log)
679
+ @request.transmit(@uri, 'req', 'payload')
680
+ end
681
+
682
+ it "should not set the ssl_client_cert if it is not provided" do
683
+ @request = RestClient::Request.new(
684
+ :method => :put,
685
+ :url => 'https://some/resource',
686
+ :payload => 'payload'
687
+ )
688
+ @net.should_not_receive(:cert=)
689
+ @http.stub(:request)
690
+ @request.stub(:process_result)
691
+ @request.stub(:response_log)
692
+ @request.transmit(@uri, 'req', 'payload')
693
+ end
694
+
695
+ it "should default to not having an ssl_client_key" do
696
+ @request.ssl_client_key.should be(nil)
697
+ end
698
+
699
+ it "should set the ssl_client_key if provided" do
700
+ @request = RestClient::Request.new(
701
+ :method => :put,
702
+ :url => 'https://some/resource',
703
+ :payload => 'payload',
704
+ :ssl_client_key => "whatsupdoc!"
705
+ )
706
+ @net.should_receive(:key=).with("whatsupdoc!")
707
+ @http.stub(:request)
708
+ @request.stub(:process_result)
709
+ @request.stub(:response_log)
710
+ @request.transmit(@uri, 'req', 'payload')
711
+ end
712
+
713
+ it "should not set the ssl_client_key if it is not provided" do
714
+ @request = RestClient::Request.new(
715
+ :method => :put,
716
+ :url => 'https://some/resource',
717
+ :payload => 'payload'
718
+ )
719
+ @net.should_not_receive(:key=)
720
+ @http.stub(:request)
721
+ @request.stub(:process_result)
722
+ @request.stub(:response_log)
723
+ @request.transmit(@uri, 'req', 'payload')
724
+ end
725
+
726
+ it "should default to not having an ssl_ca_file" do
727
+ @request.ssl_ca_file.should be(nil)
728
+ end
729
+
730
+ it "should set the ssl_ca_file if provided" do
731
+ @request = RestClient::Request.new(
732
+ :method => :put,
733
+ :url => 'https://some/resource',
734
+ :payload => 'payload',
735
+ :ssl_ca_file => "Certificate Authority File"
736
+ )
737
+ @net.should_receive(:ca_file=).with("Certificate Authority File")
738
+ @net.should_not_receive(:cert_store=)
739
+ @http.stub(:request)
740
+ @request.stub(:process_result)
741
+ @request.stub(:response_log)
742
+ @request.transmit(@uri, 'req', 'payload')
743
+ end
744
+
745
+ it "should not set the ssl_ca_file if it is not provided" do
746
+ @request = RestClient::Request.new(
747
+ :method => :put,
748
+ :url => 'https://some/resource',
749
+ :payload => 'payload'
750
+ )
751
+ @net.should_not_receive(:ca_file=)
752
+ @http.stub(:request)
753
+ @request.stub(:process_result)
754
+ @request.stub(:response_log)
755
+ @request.transmit(@uri, 'req', 'payload')
756
+ end
757
+
758
+ it "should default to not having an ssl_ca_path" do
759
+ @request.ssl_ca_path.should be(nil)
760
+ end
761
+
762
+ it "should set the ssl_ca_path if provided" do
763
+ @request = RestClient::Request.new(
764
+ :method => :put,
765
+ :url => 'https://some/resource',
766
+ :payload => 'payload',
767
+ :ssl_ca_path => "Certificate Authority Path"
768
+ )
769
+ @net.should_receive(:ca_path=).with("Certificate Authority Path")
770
+ @net.should_not_receive(:cert_store=)
771
+ @http.stub(:request)
772
+ @request.stub(:process_result)
773
+ @request.stub(:response_log)
774
+ @request.transmit(@uri, 'req', 'payload')
775
+ end
776
+
777
+ it "should not set the ssl_ca_path if it is not provided" do
778
+ @request = RestClient::Request.new(
779
+ :method => :put,
780
+ :url => 'https://some/resource',
781
+ :payload => 'payload'
782
+ )
783
+ @net.should_not_receive(:ca_path=)
784
+ @http.stub(:request)
785
+ @request.stub(:process_result)
786
+ @request.stub(:response_log)
787
+ @request.transmit(@uri, 'req', 'payload')
788
+ end
789
+
790
+ it "should set the ssl_cert_store if provided" do
791
+ store = OpenSSL::X509::Store.new
792
+ store.set_default_paths
793
+
794
+ @request = RestClient::Request.new(
795
+ :method => :put,
796
+ :url => 'https://some/resource',
797
+ :payload => 'payload',
798
+ :ssl_cert_store => store
799
+ )
800
+ @net.should_receive(:cert_store=).with(store)
801
+ @net.should_not_receive(:ca_path=)
802
+ @net.should_not_receive(:ca_file=)
803
+ @http.stub(:request)
804
+ @request.stub(:process_result)
805
+ @request.stub(:response_log)
806
+ @request.transmit(@uri, 'req', 'payload')
807
+ end
808
+
809
+ it "should by default set the ssl_cert_store if no CA info is provided" do
810
+ @request = RestClient::Request.new(
811
+ :method => :put,
812
+ :url => 'https://some/resource',
813
+ :payload => 'payload'
814
+ )
815
+ @net.should_receive(:cert_store=)
816
+ @net.should_not_receive(:ca_path=)
817
+ @net.should_not_receive(:ca_file=)
818
+ @http.stub(:request)
819
+ @request.stub(:process_result)
820
+ @request.stub(:response_log)
821
+ @request.transmit(@uri, 'req', 'payload')
822
+ end
823
+
824
+ it "should not set the ssl_cert_store if it is set falsy" do
825
+ @request = RestClient::Request.new(
826
+ :method => :put,
827
+ :url => 'https://some/resource',
828
+ :payload => 'payload',
829
+ :ssl_cert_store => nil,
830
+ )
831
+ @net.should_not_receive(:cert_store=)
832
+ @http.stub(:request)
833
+ @request.stub(:process_result)
834
+ @request.stub(:response_log)
835
+ @request.transmit(@uri, 'req', 'payload')
836
+ end
837
+
838
+ it "should not set the ssl_verify_callback by default" do
839
+ @request = RestClient::Request.new(
840
+ :method => :put,
841
+ :url => 'https://some/resource',
842
+ :payload => 'payload',
843
+ )
844
+ @net.should_not_receive(:verify_callback=)
845
+ @http.stub(:request)
846
+ @request.stub(:process_result)
847
+ @request.stub(:response_log)
848
+ @request.transmit(@uri, 'req', 'payload')
849
+ end
850
+
851
+ it "should set the ssl_verify_callback if passed" do
852
+ callback = lambda {}
853
+ @request = RestClient::Request.new(
854
+ :method => :put,
855
+ :url => 'https://some/resource',
856
+ :payload => 'payload',
857
+ :ssl_verify_callback => callback,
858
+ )
859
+ @net.should_receive(:verify_callback=).with(callback)
860
+
861
+ # we'll read cert_store on jruby
862
+ # https://github.com/jruby/jruby/issues/597
863
+ if RestClient::Platform.jruby?
864
+ allow(@net).to receive(:cert_store)
865
+ end
866
+
867
+ @http.stub(:request)
868
+ @request.stub(:process_result)
869
+ @request.stub(:response_log)
870
+ @request.transmit(@uri, 'req', 'payload')
871
+ end
872
+
873
+ # </ssl>
874
+ end
875
+
876
+ it "should still return a response object for 204 No Content responses" do
877
+ @request = RestClient::Request.new(
878
+ :method => :put,
879
+ :url => 'https://some/resource',
880
+ :payload => 'payload'
881
+ )
882
+ net_http_res = Net::HTTPNoContent.new("", "204", "No Content")
883
+ net_http_res.stub(:read_body).and_return(nil)
884
+ @http.should_receive(:request).and_return(@request.fetch_body(net_http_res))
885
+ response = @request.transmit(@uri, 'req', 'payload')
886
+ response.should_not be_nil
887
+ response.code.should eq 204
888
+ end
889
+
890
+ describe "raw response" do
891
+ it "should read the response into a binary-mode tempfile" do
892
+ @request = RestClient::Request.new(:method => "get", :url => "example.com", :raw_response => true)
893
+
894
+ tempfile = double("tempfile")
895
+ tempfile.should_receive(:binmode)
896
+ tempfile.stub(:open)
897
+ tempfile.stub(:close)
898
+ Tempfile.should_receive(:new).with("rest-client").and_return(tempfile)
899
+
900
+ net_http_res = Net::HTTPOK.new(nil, "200", "body")
901
+ net_http_res.stub(:read_body).and_return("body")
902
+ @request.fetch_body(net_http_res)
903
+ end
904
+ end
905
+ end