rest-client 1.8.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.mailmap +10 -0
  4. data/.rspec +2 -1
  5. data/.rubocop +2 -0
  6. data/.rubocop-disables.yml +386 -0
  7. data/.rubocop.yml +8 -0
  8. data/.travis.yml +56 -8
  9. data/AUTHORS +26 -1
  10. data/README.md +901 -0
  11. data/Rakefile +27 -3
  12. data/bin/restclient +3 -5
  13. data/history.md +181 -0
  14. data/lib/restclient/abstract_response.rb +172 -55
  15. data/lib/restclient/exceptions.rb +96 -55
  16. data/lib/restclient/params_array.rb +72 -0
  17. data/lib/restclient/payload.rb +70 -74
  18. data/lib/restclient/platform.rb +19 -0
  19. data/lib/restclient/raw_response.rb +21 -7
  20. data/lib/restclient/request.rb +540 -281
  21. data/lib/restclient/resource.rb +19 -9
  22. data/lib/restclient/response.rb +75 -6
  23. data/lib/restclient/utils.rb +274 -0
  24. data/lib/restclient/version.rb +2 -1
  25. data/lib/restclient.rb +21 -3
  26. data/rest-client.gemspec +12 -10
  27. data/spec/ISS.jpg +0 -0
  28. data/spec/helpers.rb +54 -0
  29. data/spec/integration/_lib.rb +1 -0
  30. data/spec/integration/capath_digicert/3513523f.0 +22 -0
  31. data/spec/integration/capath_digicert/399e7759.0 +22 -0
  32. data/spec/integration/capath_digicert/digicert.crt +20 -17
  33. data/spec/integration/certs/digicert.crt +20 -17
  34. data/spec/integration/httpbin_spec.rb +128 -0
  35. data/spec/integration/integration_spec.rb +97 -14
  36. data/spec/integration/request_spec.rb +25 -2
  37. data/spec/spec_helper.rb +28 -1
  38. data/spec/unit/_lib.rb +1 -0
  39. data/spec/unit/abstract_response_spec.rb +95 -38
  40. data/spec/unit/exceptions_spec.rb +41 -28
  41. data/spec/unit/params_array_spec.rb +36 -0
  42. data/spec/unit/payload_spec.rb +118 -68
  43. data/spec/unit/raw_response_spec.rb +10 -6
  44. data/spec/unit/request2_spec.rb +34 -12
  45. data/spec/unit/request_spec.rb +745 -424
  46. data/spec/unit/resource_spec.rb +31 -27
  47. data/spec/unit/response_spec.rb +134 -57
  48. data/spec/unit/restclient_spec.rb +16 -15
  49. data/spec/unit/utils_spec.rb +147 -0
  50. data/spec/unit/windows/root_certs_spec.rb +3 -3
  51. metadata +79 -29
  52. data/README.rdoc +0 -324
  53. data/spec/integration/capath_digicert/244b5494.0 +0 -19
  54. data/spec/integration/capath_digicert/81b9768f.0 +0 -19
  55. data/spec/unit/master_shake.jpg +0 -0
@@ -1,120 +1,206 @@
1
- require 'spec_helper'
1
+ require_relative './_lib'
2
2
 
3
- describe RestClient::Request do
3
+ describe RestClient::Request, :include_helpers do
4
4
  before do
5
5
  @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
6
6
 
7
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)
8
+ allow(@uri).to receive(:request_uri).and_return('/resource')
9
+ allow(@uri).to receive(:hostname).and_return('some')
10
+ allow(@uri).to receive(:port).and_return(80)
11
11
 
12
12
  @net = double("net::http base")
13
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=)
14
+
15
+ allow(Net::HTTP).to receive(:new).and_return(@net)
16
+
17
+ allow(@net).to receive(:start).and_yield(@http)
18
+ allow(@net).to receive(:use_ssl=)
19
+ allow(@net).to receive(:verify_mode=)
20
+ allow(@net).to receive(:verify_callback=)
19
21
  allow(@net).to receive(:ciphers=)
20
22
  allow(@net).to receive(:cert_store=)
21
23
  RestClient.log = nil
22
24
  end
23
25
 
24
- it "accept */* mimetype, preferring xml" do
25
- @request.default_headers[:accept].should eq '*/*; q=0.5, application/xml'
26
+ it "accept */* mimetype" do
27
+ expect(@request.default_headers[:accept]).to eq '*/*'
26
28
  end
27
29
 
28
- describe "compression" do
30
+ it "processes a successful result" do
31
+ res = res_double
32
+ allow(res).to receive(:code).and_return("200")
33
+ allow(res).to receive(:body).and_return('body')
34
+ allow(res).to receive(:[]).with('content-encoding').and_return(nil)
35
+ expect(@request.send(:process_result, res, Time.now).body).to eq 'body'
36
+ expect(@request.send(:process_result, res, Time.now).to_s).to eq 'body'
37
+ end
29
38
 
30
- it "decodes an uncompressed result body by passing it straight through" do
31
- RestClient::Request.decode(nil, 'xyz').should eq 'xyz'
39
+ it "doesn't classify successful requests as failed" do
40
+ 203.upto(207) do |code|
41
+ res = res_double
42
+ allow(res).to receive(:code).and_return(code.to_s)
43
+ allow(res).to receive(:body).and_return("")
44
+ allow(res).to receive(:[]).with('content-encoding').and_return(nil)
45
+ expect(@request.send(:process_result, res, Time.now)).to be_empty
32
46
  end
47
+ end
33
48
 
34
- it "doesn't fail for nil bodies" do
35
- RestClient::Request.decode('gzip', nil).should be_nil
49
+ describe '.normalize_url' do
50
+ it "adds http:// to the front of resources specified in the syntax example.com/resource" do
51
+ expect(@request.normalize_url('example.com/resource')).to eq 'http://example.com/resource'
36
52
  end
37
53
 
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"
54
+ it 'adds http:// to resources containing a colon' do
55
+ expect(@request.normalize_url('example.com:1234')).to eq 'http://example.com:1234'
41
56
  end
42
57
 
43
- it "ingores gzip for empty bodies" do
44
- RestClient::Request.decode('gzip', '').should be_empty
58
+ it 'does not add http:// to the front of https resources' do
59
+ expect(@request.normalize_url('https://example.com/resource')).to eq 'https://example.com/resource'
45
60
  end
46
61
 
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"
62
+ it 'does not add http:// to the front of capital HTTP resources' do
63
+ expect(@request.normalize_url('HTTP://example.com/resource')).to eq 'HTTP://example.com/resource'
49
64
  end
50
- end
51
65
 
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
66
+ it 'does not add http:// to the front of capital HTTPS resources' do
67
+ expect(@request.normalize_url('HTTPS://example.com/resource')).to eq 'HTTPS://example.com/resource'
68
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
69
 
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')
70
+ it 'raises with invalid URI' do
71
+ expect {
72
+ RestClient::Request.new(method: :get, url: 'http://a@b:c')
73
+ }.to raise_error(URI::InvalidURIError)
74
+ expect {
75
+ RestClient::Request.new(method: :get, url: 'http://::')
76
+ }.to raise_error(URI::InvalidURIError)
77
+ end
79
78
  end
80
79
 
81
80
  describe "user - password" do
82
81
  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'
82
+ @request.send(:parse_url_with_auth!, 'http://joe:pass1@example.com/resource')
83
+ expect(@request.user).to eq 'joe'
84
+ expect(@request.password).to eq 'pass1'
87
85
  end
88
86
 
89
87
  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'
88
+ @request.send(:parse_url_with_auth!, 'http://joe%20:pass1@example.com/resource')
89
+ expect(@request.user).to eq 'joe '
90
+ expect(@request.password).to eq 'pass1'
94
91
  end
95
92
 
96
93
  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'
94
+ request = RestClient::Request.new(method: :get, url: 'http://example.com/resource', user: 'beth', password: 'pass2')
95
+ expect(request.user).to eq 'beth'
96
+ expect(request.password).to eq 'pass2'
97
+ end
98
+
99
+ it 'uses the username and password from the URL' do
100
+ request = RestClient::Request.new(method: :get, url: 'http://person:secret@example.com/resource')
101
+ expect(request.user).to eq 'person'
102
+ expect(request.password).to eq 'secret'
103
+ end
104
+
105
+ it 'overrides URL user/pass with explicit options' do
106
+ request = RestClient::Request.new(method: :get, url: 'http://person:secret@example.com/resource', user: 'beth', password: 'pass2')
107
+ expect(request.user).to eq 'beth'
108
+ expect(request.password).to eq 'pass2'
102
109
  end
103
110
  end
104
111
 
105
112
  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'})
113
+ cookies_arr = [
114
+ HTTP::Cookie.new('session_id', '1', domain: 'example.com', path: '/'),
115
+ HTTP::Cookie.new('user_id', 'someone', domain: 'example.com', path: '/'),
116
+ ]
117
+
118
+ jar = HTTP::CookieJar.new
119
+ cookies_arr.each {|c| jar << c }
120
+
121
+ # test Hash, HTTP::CookieJar, and Array<HTTP::Cookie> modes
122
+ [
123
+ {session_id: '1', user_id: 'someone'},
124
+ jar,
125
+ cookies_arr
126
+ ].each do |cookies|
127
+ [true, false].each do |in_headers|
128
+ if in_headers
129
+ opts = {headers: {cookies: cookies}}
130
+ else
131
+ opts = {cookies: cookies}
132
+ end
133
+
134
+ request = RestClient::Request.new(method: :get, url: 'example.com', **opts)
135
+ expect(request).to receive(:default_headers).and_return({'Foo' => 'bar'})
136
+ expect(request.make_headers({})).to eq({'Foo' => 'bar', 'Cookie' => 'session_id=1; user_id=someone'})
137
+ expect(request.make_cookie_header).to eq 'session_id=1; user_id=someone'
138
+ expect(request.cookies).to eq({'session_id' => '1', 'user_id' => 'someone'})
139
+ expect(request.cookie_jar.cookies.length).to eq 2
140
+ expect(request.cookie_jar.object_id).not_to eq jar.object_id # make sure we dup it
141
+ end
142
+ end
143
+
144
+ # test with no cookies
145
+ request = RestClient::Request.new(method: :get, url: 'example.com')
146
+ expect(request).to receive(:default_headers).and_return({'Foo' => 'bar'})
147
+ expect(request.make_headers({})).to eq({'Foo' => 'bar'})
148
+ expect(request.make_cookie_header).to be_nil
149
+ expect(request.cookies).to eq({})
150
+ expect(request.cookie_jar.cookies.length).to eq 0
151
+ end
152
+
153
+ it 'strips out cookies set for a different domain name' do
154
+ jar = HTTP::CookieJar.new
155
+ jar << HTTP::Cookie.new('session_id', '1', domain: 'other.example.com', path: '/')
156
+ jar << HTTP::Cookie.new('user_id', 'someone', domain: 'other.example.com', path: '/')
157
+
158
+ request = RestClient::Request.new(method: :get, url: 'www.example.com', cookies: jar)
159
+ expect(request).to receive(:default_headers).and_return({'Foo' => 'bar'})
160
+ expect(request.make_headers({})).to eq({'Foo' => 'bar'})
161
+ expect(request.make_cookie_header).to eq nil
162
+ expect(request.cookies).to eq({})
163
+ expect(request.cookie_jar.cookies.length).to eq 2
164
+ end
165
+
166
+ it 'assumes default domain and path for cookies set by hash' do
167
+ request = RestClient::Request.new(method: :get, url: 'www.example.com', cookies: {'session_id' => '1'})
168
+ expect(request.cookie_jar.cookies.length).to eq 1
169
+
170
+ cookie = request.cookie_jar.cookies.first
171
+ expect(cookie).to be_a(HTTP::Cookie)
172
+ expect(cookie.domain).to eq('www.example.com')
173
+ expect(cookie.for_domain?).to be_truthy
174
+ expect(cookie.path).to eq('/')
175
+ end
176
+
177
+ it 'rejects or warns with contradictory cookie options' do
178
+ # same opt in two different places
179
+ expect {
180
+ RestClient::Request.new(method: :get, url: 'example.com',
181
+ cookies: {bar: '456'},
182
+ headers: {cookies: {foo: '123'}})
183
+ }.to raise_error(ArgumentError, /Cannot pass :cookies in Request.*headers/)
184
+
185
+ # :cookies opt and Cookie header
186
+ [
187
+ {cookies: {foo: '123'}, headers: {cookie: 'foo'}},
188
+ {cookies: {foo: '123'}, headers: {'Cookie' => 'foo'}},
189
+ {headers: {cookies: {foo: '123'}, cookie: 'foo'}},
190
+ {headers: {cookies: {foo: '123'}, 'Cookie' => 'foo'}},
191
+ ].each do |opts|
192
+ expect(fake_stderr {
193
+ RestClient::Request.new(method: :get, url: 'example.com', **opts)
194
+ }).to match(/warning: overriding "Cookie" header with :cookies option/)
195
+ end
110
196
  end
111
197
 
112
198
  it "does not escape or unescape cookies" do
113
199
  cookie = 'Foo%20:Bar%0A~'
114
200
  @request = RestClient::Request.new(:method => 'get', :url => 'example.com',
115
201
  :cookies => {:test => cookie})
116
- @request.should_receive(:default_headers).and_return({'Foo' => 'bar'})
117
- @request.make_headers({}).should eq({
202
+ expect(@request).to receive(:default_headers).and_return({'Foo' => 'bar'})
203
+ expect(@request.make_headers({})).to eq({
118
204
  'Foo' => 'bar',
119
205
  'Cookie' => "test=#{cookie}"
120
206
  })
@@ -124,244 +210,409 @@ describe RestClient::Request do
124
210
  # Cookie validity is something of a mess, but we should reject the worst of
125
211
  # the RFC 6265 (4.1.1) prohibited characters such as control characters.
126
212
 
127
- ['', 'foo=bar', 'foo;bar', "foo\nbar"].each do |cookie_name|
128
- lambda {
213
+ ['foo=bar', 'foo;bar', "foo\nbar"].each do |cookie_name|
214
+ expect {
129
215
  RestClient::Request.new(:method => 'get', :url => 'example.com',
130
216
  :cookies => {cookie_name => 'value'})
131
- }.should raise_error(ArgumentError, /\AInvalid cookie name/)
217
+ }.to raise_error(ArgumentError, /\AInvalid cookie name/i)
132
218
  end
219
+
220
+ cookie_name = ''
221
+ expect {
222
+ RestClient::Request.new(:method => 'get', :url => 'example.com',
223
+ :cookies => {cookie_name => 'value'})
224
+ }.to raise_error(ArgumentError, /cookie name cannot be empty/i)
133
225
  end
134
226
 
135
227
  it "rejects cookie values containing invalid characters" do
136
228
  # Cookie validity is something of a mess, but we should reject the worst of
137
229
  # the RFC 6265 (4.1.1) prohibited characters such as control characters.
138
230
 
139
- ['foo,bar', 'foo;bar', "foo\nbar"].each do |cookie_value|
140
- lambda {
231
+ ["foo\tbar", "foo\nbar"].each do |cookie_value|
232
+ expect {
141
233
  RestClient::Request.new(:method => 'get', :url => 'example.com',
142
234
  :cookies => {'test' => cookie_value})
143
- }.should raise_error(ArgumentError, /\AInvalid cookie value/)
235
+ }.to raise_error(ArgumentError, /\AInvalid cookie value/i)
144
236
  end
145
237
  end
146
238
 
239
+ it 'warns when overriding existing headers via payload' do
240
+ expect(fake_stderr {
241
+ RestClient::Request.new(method: :post, url: 'example.com',
242
+ payload: {'foo' => 1}, headers: {content_type: :json})
243
+ }).to match(/warning: Overriding "Content-Type" header/i)
244
+ expect(fake_stderr {
245
+ RestClient::Request.new(method: :post, url: 'example.com',
246
+ payload: {'foo' => 1}, headers: {'Content-Type' => 'application/json'})
247
+ }).to match(/warning: Overriding "Content-Type" header/i)
248
+
249
+ expect(fake_stderr {
250
+ RestClient::Request.new(method: :post, url: 'example.com',
251
+ payload: '123456', headers: {content_length: '20'})
252
+ }).to match(/warning: Overriding "Content-Length" header/i)
253
+ expect(fake_stderr {
254
+ RestClient::Request.new(method: :post, url: 'example.com',
255
+ payload: '123456', headers: {'Content-Length' => '20'})
256
+ }).to match(/warning: Overriding "Content-Length" header/i)
257
+ end
258
+
259
+ it "does not warn when overriding user header with header derived from payload if those header values were identical" do
260
+ expect(fake_stderr {
261
+ RestClient::Request.new(method: :post, url: 'example.com',
262
+ payload: {'foo' => '123456'}, headers: { 'Content-Type' => 'application/x-www-form-urlencoded' })
263
+ }).not_to match(/warning: Overriding "Content-Type" header/i)
264
+ end
265
+
266
+ it 'does not warn for a normal looking payload' do
267
+ expect(fake_stderr {
268
+ RestClient::Request.new(method: :post, url: 'example.com', payload: 'payload')
269
+ RestClient::Request.new(method: :post, url: 'example.com', payload: 'payload', headers: {content_type: :json})
270
+ RestClient::Request.new(method: :post, url: 'example.com', payload: {'foo' => 'bar'})
271
+ }).to eq ''
272
+ end
273
+
147
274
  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'
275
+ expect(Netrc).to receive(:read).and_return('example.com' => ['a', 'b'])
276
+ request = RestClient::Request.new(:method => :put, :url => 'http://example.com/', :payload => 'payload')
277
+ expect(request.user).to eq 'a'
278
+ expect(request.password).to eq 'b'
153
279
  end
154
280
 
155
281
  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'
282
+ allow(Netrc).to receive(:read).and_return('example.com' => ['a', 'b'])
283
+ request = RestClient::Request.new(:method => :put, :url => 'http://joe%20:pass1@example.com/', :payload => 'payload')
284
+ expect(request.user).to eq 'joe '
285
+ expect(request.password).to eq 'pass1'
161
286
  end
162
287
 
163
288
  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
289
+ expect(@request.net_http_request_class(:put)).to eq Net::HTTP::Put
165
290
  end
166
291
 
167
292
  describe "user headers" do
168
293
  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' })
294
+ expect(@request).to receive(:default_headers).and_return({:accept => '*/*'})
170
295
  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"
296
+ expect(headers).to have_key "Accept-Encoding"
297
+ expect(headers["Accept-Encoding"]).to eq "gzip"
298
+ expect(headers).to have_key "Accept"
299
+ expect(headers["Accept"]).to eq "application/json"
175
300
  end
176
301
 
177
302
  it "prefers the user header when the same header exists in the defaults" do
178
- @request.should_receive(:default_headers).and_return({ '1' => '2' })
303
+ expect(@request).to receive(:default_headers).and_return({ '1' => '2' })
179
304
  headers = @request.make_headers('1' => '3')
180
- headers.should have_key('1')
181
- headers['1'].should eq '3'
305
+ expect(headers).to have_key('1')
306
+ expect(headers['1']).to eq '3'
182
307
  end
183
308
 
184
309
  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' })
310
+ expect(@request).to receive(:default_headers).and_return({ '1' => '2' })
186
311
  headers = @request.make_headers('1' => 3)
187
- headers.should have_key('1')
188
- headers['1'].should eq '3'
312
+ expect(headers).to have_key('1')
313
+ expect(headers['1']).to eq '3'
189
314
  end
190
315
  end
191
316
 
192
317
  describe "header symbols" do
193
318
 
194
319
  it "converts header symbols from :content_type to 'Content-Type'" do
195
- @request.should_receive(:default_headers).and_return({})
320
+ expect(@request).to receive(:default_headers).and_return({})
196
321
  headers = @request.make_headers(:content_type => 'abc')
197
- headers.should have_key('Content-Type')
198
- headers['Content-Type'].should eq 'abc'
322
+ expect(headers).to have_key('Content-Type')
323
+ expect(headers['Content-Type']).to eq 'abc'
199
324
  end
200
325
 
201
326
  it "converts content-type from extension to real content-type" do
202
- @request.should_receive(:default_headers).and_return({})
327
+ expect(@request).to receive(:default_headers).and_return({})
203
328
  headers = @request.make_headers(:content_type => 'json')
204
- headers.should have_key('Content-Type')
205
- headers['Content-Type'].should eq 'application/json'
329
+ expect(headers).to have_key('Content-Type')
330
+ expect(headers['Content-Type']).to eq 'application/json'
206
331
  end
207
332
 
208
333
  it "converts accept from extension(s) to real content-type(s)" do
209
- @request.should_receive(:default_headers).and_return({})
334
+ expect(@request).to receive(:default_headers).and_return({})
210
335
  headers = @request.make_headers(:accept => 'json, mp3')
211
- headers.should have_key('Accept')
212
- headers['Accept'].should eq 'application/json, audio/mpeg'
336
+ expect(headers).to have_key('Accept')
337
+ expect(headers['Accept']).to eq 'application/json, audio/mpeg'
213
338
 
214
- @request.should_receive(:default_headers).and_return({})
339
+ expect(@request).to receive(:default_headers).and_return({})
215
340
  headers = @request.make_headers(:accept => :json)
216
- headers.should have_key('Accept')
217
- headers['Accept'].should eq 'application/json'
341
+ expect(headers).to have_key('Accept')
342
+ expect(headers['Accept']).to eq 'application/json'
218
343
  end
219
344
 
220
345
  it "only convert symbols in header" do
221
- @request.should_receive(:default_headers).and_return({})
346
+ expect(@request).to receive(:default_headers).and_return({})
222
347
  headers = @request.make_headers({:foo_bar => 'value', "bar_bar" => 'value'})
223
- headers['Foo-Bar'].should eq 'value'
224
- headers['bar_bar'].should eq 'value'
348
+ expect(headers['Foo-Bar']).to eq 'value'
349
+ expect(headers['bar_bar']).to eq 'value'
225
350
  end
226
351
 
227
352
  it "converts header values to strings" do
228
- @request.make_headers('A' => 1)['A'].should eq '1'
353
+ expect(@request.make_headers('A' => 1)['A']).to eq '1'
229
354
  end
230
355
  end
231
356
 
232
357
  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
358
  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))
359
+ expect(@request).to receive(:net_http_request_class).with('put').and_return(klass)
360
+ expect(klass).to receive(:new).and_return('result')
361
+ expect(@request).to receive(:transmit).with(@request.uri, 'result', kind_of(RestClient::Payload::Base))
362
+ @request.execute
363
+ end
364
+
365
+ it "IPv6: executes by constructing the Net::HTTP object, headers, and payload and calling transmit" do
366
+ @request = RestClient::Request.new(:method => :put, :url => 'http://[::1]/some/resource', :payload => 'payload')
367
+ klass = double("net:http class")
368
+ expect(@request).to receive(:net_http_request_class).with('put').and_return(klass)
369
+
370
+ if RUBY_VERSION >= "2.0.0"
371
+ expect(klass).to receive(:new).with(kind_of(URI), kind_of(Hash)).and_return('result')
372
+ else
373
+ expect(klass).to receive(:new).with(kind_of(String), kind_of(Hash)).and_return('result')
374
+ end
375
+
376
+ expect(@request).to receive(:transmit)
238
377
  @request.execute
239
378
  end
240
379
 
380
+ # TODO: almost none of these tests should actually call transmit, which is
381
+ # part of the private API
382
+
241
383
  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')
384
+ expect(@http).to receive(:request).with('req', 'payload')
385
+ expect(@request).to receive(:process_result)
386
+ @request.send(:transmit, @uri, 'req', 'payload')
245
387
  end
246
388
 
389
+ # TODO: most of these payload tests are historical relics that actually
390
+ # belong in payload_spec.rb. Or we need new tests that actually cover the way
391
+ # that Request#initialize or Request#execute uses the payload.
247
392
  describe "payload" do
248
393
  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)
394
+ expect(@http).to receive(:request).with('req', nil)
395
+ expect(@request).to receive(:process_result)
396
+ allow(@request).to receive(:response_log)
397
+ @request.send(:transmit, @uri, 'req', nil)
253
398
  end
254
399
 
255
400
  it "passes non-hash payloads straight through" do
256
- @request.process_payload("x").should eq "x"
401
+ expect(RestClient::Payload.generate("x").to_s).to eq "x"
257
402
  end
258
403
 
259
404
  it "converts a hash payload to urlencoded data" do
260
- @request.process_payload(:a => 'b c+d').should eq "a=b%20c%2Bd"
405
+ expect(RestClient::Payload.generate(:a => 'b c+d').to_s).to eq "a=b+c%2Bd"
261
406
  end
262
407
 
263
408
  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')
409
+ payload = RestClient::Payload.generate(:user => { :name => 'joe', :location => { :country => 'USA', :state => 'CA' }}).to_s
410
+ expect(payload).to include('user[name]=joe')
411
+ expect(payload).to include('user[location][country]=USA')
412
+ expect(payload).to include('user[location][state]=CA')
268
413
  end
269
414
  end
270
415
 
271
416
  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'
417
+ req = RestClient::Request.new(method: :post, url: 'http://some/resource', payload: {a: 1})
418
+ expect(req.processed_headers.fetch('Content-Type')).to eq 'application/x-www-form-urlencoded'
274
419
  end
275
420
 
276
421
  describe "credentials" do
277
422
  it "sets up the credentials prior to the request" do
278
- @http.stub(:request)
423
+ allow(@http).to receive(:request)
279
424
 
280
- @request.stub(:process_result)
281
- @request.stub(:response_log)
425
+ allow(@request).to receive(:process_result)
426
+ allow(@request).to receive(:response_log)
282
427
 
283
- @request.stub(:user).and_return('joe')
284
- @request.stub(:password).and_return('mypass')
285
- @request.should_receive(:setup_credentials).with('req')
428
+ allow(@request).to receive(:user).and_return('joe')
429
+ allow(@request).to receive(:password).and_return('mypass')
430
+ expect(@request).to receive(:setup_credentials).with('req')
286
431
 
287
- @request.transmit(@uri, 'req', nil)
432
+ @request.send(:transmit, @uri, 'req', nil)
288
433
  end
289
434
 
290
435
  it "does not attempt to send any credentials if user is nil" do
291
- @request.stub(:user).and_return(nil)
436
+ allow(@request).to receive(:user).and_return(nil)
292
437
  req = double("request")
293
- req.should_not_receive(:basic_auth)
294
- @request.setup_credentials(req)
438
+ expect(req).not_to receive(:basic_auth)
439
+ @request.send(:setup_credentials, req)
295
440
  end
296
441
 
297
442
  it "setup credentials when there's a user" do
298
- @request.stub(:user).and_return('joe')
299
- @request.stub(:password).and_return('mypass')
443
+ allow(@request).to receive(:user).and_return('joe')
444
+ allow(@request).to receive(:password).and_return('mypass')
300
445
  req = double("request")
301
- req.should_receive(:basic_auth).with('joe', 'mypass')
302
- @request.setup_credentials(req)
446
+ expect(req).to receive(:basic_auth).with('joe', 'mypass')
447
+ @request.send(:setup_credentials, req)
448
+ end
449
+
450
+ it "does not attempt to send credentials if Authorization header is set" do
451
+ ['Authorization', 'authorization', 'auTHORization', :authorization].each do |authorization|
452
+ headers = {authorization => 'Token abc123'}
453
+ request = RestClient::Request.new(method: :get, url: 'http://some/resource', headers: headers, user: 'joe', password: 'mypass')
454
+ req = double("net::http request")
455
+ expect(req).not_to receive(:basic_auth)
456
+ request.send(:setup_credentials, req)
457
+ end
303
458
  end
304
459
  end
305
460
 
306
461
  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)
462
+ allow(@http).to receive(:request).and_raise(EOFError)
463
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestClient::ServerBrokeConnection)
309
464
  end
310
465
 
311
466
  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)
467
+ allow(@http).to receive(:request).and_raise(OpenSSL::SSL::SSLError)
468
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(OpenSSL::SSL::SSLError)
469
+ end
470
+
471
+ it "catches Timeout::Error and raise the more informative ReadTimeout" do
472
+ allow(@http).to receive(:request).and_raise(Timeout::Error)
473
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestClient::Exceptions::ReadTimeout)
314
474
  end
315
475
 
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)
476
+ it "catches Errno::ETIMEDOUT and raise the more informative ReadTimeout" do
477
+ allow(@http).to receive(:request).and_raise(Errno::ETIMEDOUT)
478
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestClient::Exceptions::ReadTimeout)
319
479
  end
320
480
 
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)
481
+ it "catches Net::ReadTimeout and raises RestClient's ReadTimeout",
482
+ :if => defined?(Net::ReadTimeout) do
483
+ allow(@http).to receive(:request).and_raise(Net::ReadTimeout)
484
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestClient::Exceptions::ReadTimeout)
324
485
  end
325
486
 
487
+ it "catches Net::OpenTimeout and raises RestClient's OpenTimeout",
488
+ :if => defined?(Net::OpenTimeout) do
489
+ allow(@http).to receive(:request).and_raise(Net::OpenTimeout)
490
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestClient::Exceptions::OpenTimeout)
491
+ end
492
+
493
+ it "uses correct error message for ReadTimeout",
494
+ :if => defined?(Net::ReadTimeout) do
495
+ allow(@http).to receive(:request).and_raise(Net::ReadTimeout)
496
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestClient::Exceptions::ReadTimeout, 'Timed out reading data from server')
497
+ end
498
+
499
+ it "uses correct error message for OpenTimeout",
500
+ :if => defined?(Net::OpenTimeout) do
501
+ allow(@http).to receive(:request).and_raise(Net::OpenTimeout)
502
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestClient::Exceptions::OpenTimeout, 'Timed out connecting to server')
503
+ end
504
+
505
+
326
506
  it "class method execute wraps constructor" do
327
507
  req = double("rest request")
328
- RestClient::Request.should_receive(:new).with(1 => 2).and_return(req)
329
- req.should_receive(:execute)
508
+ expect(RestClient::Request).to receive(:new).with(1 => 2).and_return(req)
509
+ expect(req).to receive(:execute)
330
510
  RestClient::Request.execute(1 => 2)
331
511
  end
332
512
 
333
513
  describe "exception" do
334
514
  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)
515
+ res = res_double(:code => '401', :[] => ['content-encoding' => ''], :body => '' )
516
+ expect { @request.send(:process_result, res, Time.now) }.to raise_error(RestClient::Unauthorized)
337
517
  end
338
518
 
339
519
  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)
520
+ res = res_double(:code => '404', :[] => ['content-encoding' => ''], :body => '' )
521
+ expect { @request.send(:process_result, res, Time.now) }.to raise_error(RestClient::ResourceNotFound)
342
522
  end
343
523
 
344
524
  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)
525
+ res = res_double(:code => '500', :[] => ['content-encoding' => ''], :body => '' )
526
+ expect { @request.send(:process_result, res, Time.now) }.to raise_error(RestClient::InternalServerError)
347
527
  end
348
528
  end
349
529
 
350
530
  describe "block usage" do
351
531
  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"
532
+ res = res_double(:code => '401', :[] => ['content-encoding' => ''], :body => '' )
533
+ expect(@request.send(:process_result, res, Time.now){|response, request| "foo"}).to eq "foo"
354
534
  end
355
535
  end
356
536
 
357
537
  describe "proxy" do
538
+ before do
539
+ # unstub Net::HTTP creation since we need to test it
540
+ allow(Net::HTTP).to receive(:new).and_call_original
541
+
542
+ @proxy_req = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
543
+ end
544
+
358
545
  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
546
+ allow(RestClient).to receive(:proxy).and_return("http://example.com/")
547
+ allow(RestClient).to receive(:proxy_set?).and_return(true)
548
+ expect(@proxy_req.net_http_object('host', 80).proxy?).to be true
549
+ end
550
+
551
+ it "creates a proxy class with the correct address if a IPv6 proxy url is given" do
552
+ allow(RestClient).to receive(:proxy).and_return("http://[::1]/")
553
+ allow(RestClient).to receive(:proxy_set?).and_return(true)
554
+ expect(@proxy_req.net_http_object('host', 80).proxy?).to be true
555
+ expect(@proxy_req.net_http_object('host', 80).proxy_address).to eq('::1')
361
556
  end
362
557
 
363
558
  it "creates a non-proxy class if a proxy url is not given" do
364
- @request.net_http_class.proxy_class?.should be_false
559
+ expect(@proxy_req.net_http_object('host', 80).proxy?).to be_falsey
560
+ end
561
+
562
+ it "disables proxy on a per-request basis" do
563
+ allow(RestClient).to receive(:proxy).and_return('http://example.com')
564
+ allow(RestClient).to receive(:proxy_set?).and_return(true)
565
+ expect(@proxy_req.net_http_object('host', 80).proxy?).to be true
566
+
567
+ disabled_req = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :proxy => nil)
568
+ expect(disabled_req.net_http_object('host', 80).proxy?).to be_falsey
569
+ end
570
+
571
+ it "sets proxy on a per-request basis" do
572
+ expect(@proxy_req.net_http_object('some', 80).proxy?).to be_falsey
573
+
574
+ req = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :proxy => 'http://example.com')
575
+ expect(req.net_http_object('host', 80).proxy?).to be true
576
+ end
577
+
578
+ it "overrides proxy from environment", if: RUBY_VERSION >= '2.0' do
579
+ allow(ENV).to receive(:[]).with("http_proxy").and_return("http://127.0.0.1")
580
+ allow(ENV).to receive(:[]).with("no_proxy").and_return(nil)
581
+ allow(ENV).to receive(:[]).with("NO_PROXY").and_return(nil)
582
+ allow(Netrc).to receive(:read).and_return({})
583
+
584
+ req = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
585
+ obj = req.net_http_object('host', 80)
586
+ expect(obj.proxy?).to be true
587
+ expect(obj.proxy_address).to eq '127.0.0.1'
588
+
589
+ # test original method .proxy?
590
+ req = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :proxy => nil)
591
+ obj = req.net_http_object('host', 80)
592
+ expect(obj.proxy?).to be_falsey
593
+
594
+ # stub RestClient.proxy_set? to peek into implementation
595
+ allow(RestClient).to receive(:proxy_set?).and_return(true)
596
+ req = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
597
+ obj = req.net_http_object('host', 80)
598
+ expect(obj.proxy?).to be_falsey
599
+
600
+ # test stubbed Net::HTTP.new
601
+ req = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :proxy => nil)
602
+ expect(Net::HTTP).to receive(:new).with('host', 80, nil, nil, nil, nil)
603
+ req.net_http_object('host', 80)
604
+ end
605
+
606
+ it "overrides global proxy with per-request proxy" do
607
+ allow(RestClient).to receive(:proxy).and_return('http://example.com')
608
+ allow(RestClient).to receive(:proxy_set?).and_return(true)
609
+ obj = @proxy_req.net_http_object('host', 80)
610
+ expect(obj.proxy?).to be true
611
+ expect(obj.proxy_address).to eq 'example.com'
612
+
613
+ req = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :proxy => 'http://127.0.0.1/')
614
+ expect(req.net_http_object('host', 80).proxy?).to be true
615
+ expect(req.net_http_object('host', 80).proxy_address).to eq('127.0.0.1')
365
616
  end
366
617
  end
367
618
 
@@ -369,189 +620,231 @@ describe RestClient::Request do
369
620
  describe "logging" do
370
621
  it "logs a get request" do
371
622
  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}
623
+ RestClient::Request.new(:method => :get, :url => 'http://url', :headers => {:user_agent => 'rest-client'}).log_request
624
+ expect(log[0]).to eq %Q{RestClient.get "http://url", "Accept"=>"*/*", "User-Agent"=>"rest-client"\n}
374
625
  end
375
626
 
376
627
  it "logs a post request with a small payload" do
377
628
  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}
629
+ RestClient::Request.new(:method => :post, :url => 'http://url', :payload => 'foo', :headers => {:user_agent => 'rest-client'}).log_request
630
+ expect(log[0]).to eq %Q{RestClient.post "http://url", "foo", "Accept"=>"*/*", "Content-Length"=>"3", "User-Agent"=>"rest-client"\n}
380
631
  end
381
632
 
382
633
  it "logs a post request with a large payload" do
383
634
  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}
635
+ RestClient::Request.new(:method => :post, :url => 'http://url', :payload => ('x' * 1000), :headers => {:user_agent => 'rest-client'}).log_request
636
+ expect(log[0]).to eq %Q{RestClient.post "http://url", 1000 byte(s) length, "Accept"=>"*/*", "Content-Length"=>"1000", "User-Agent"=>"rest-client"\n}
386
637
  end
387
638
 
388
639
  it "logs input headers as a hash" do
389
640
  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}
641
+ RestClient::Request.new(:method => :get, :url => 'http://url', :headers => { :accept => 'text/plain', :user_agent => 'rest-client' }).log_request
642
+ expect(log[0]).to eq %Q{RestClient.get "http://url", "Accept"=>"text/plain", "User-Agent"=>"rest-client"\n}
392
643
  end
393
644
 
394
645
  it "logs a response including the status code, content type, and result body size in bytes" do
395
646
  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"
647
+ res = res_double(code: '200', class: Net::HTTPOK, body: 'abcd')
648
+ allow(res).to receive(:[]).with('Content-type').and_return('text/html')
649
+ response = response_from_res_double(res, @request)
650
+ response.log_response
651
+ expect(log).to eq ["# => 200 OK | text/html 4 bytes, 1.00s\n"]
400
652
  end
401
653
 
402
654
  it "logs a response with a nil Content-type" do
403
655
  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"
656
+ res = res_double(code: '200', class: Net::HTTPOK, body: 'abcd')
657
+ allow(res).to receive(:[]).with('Content-type').and_return(nil)
658
+ response = response_from_res_double(res, @request)
659
+ response.log_response
660
+ expect(log).to eq ["# => 200 OK | 4 bytes, 1.00s\n"]
408
661
  end
409
662
 
410
663
  it "logs a response with a nil body" do
411
664
  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"
665
+ res = res_double(code: '200', class: Net::HTTPOK, body: nil)
666
+ allow(res).to receive(:[]).with('Content-type').and_return('text/html; charset=utf-8')
667
+ response = response_from_res_double(res, @request)
668
+ response.log_response
669
+ expect(log).to eq ["# => 200 OK | text/html 0 bytes, 1.00s\n"]
416
670
  end
417
671
 
418
672
  it 'does not log request password' do
419
673
  log = RestClient.log = []
420
- RestClient::Request.new(:method => :get, :url => 'http://user:password@url', :headers => {:user_agent => 'rest-client', :accept => '*/*'}).log_request
421
- log[0].should eq %Q{RestClient.get "http://user:REDACTED@url", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "User-Agent"=>"rest-client"\n}
674
+ RestClient::Request.new(:method => :get, :url => 'http://user:password@url', :headers => {:user_agent => 'rest-client'}).log_request
675
+ expect(log[0]).to eq %Q{RestClient.get "http://user:REDACTED@url", "Accept"=>"*/*", "User-Agent"=>"rest-client"\n}
422
676
  end
423
677
 
424
- it 'logs invalid URIs, even though they will fail elsewhere' do
425
- log = RestClient.log = []
426
- RestClient::Request.new(:method => :get, :url => 'http://a@b:c', :headers => {:user_agent => 'rest-client', :accept => '*/*'}).log_request
427
- log[0].should eq %Q{RestClient.get "[invalid uri]", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "User-Agent"=>"rest-client"\n}
678
+ it 'logs to a passed logger, if provided' do
679
+ logger = double('logger', '<<' => true)
680
+ expect(logger).to receive(:<<)
681
+ RestClient::Request.new(:method => :get, :url => 'http://user:password@url', log: logger).log_request
428
682
  end
429
683
  end
430
684
 
431
685
  it "strips the charset from the response content type" do
432
686
  log = RestClient.log = []
433
- res = double('result', :code => '200', :class => Net::HTTPOK, :body => 'abcd')
434
- res.stub(:[]).with('Content-type').and_return('text/html; charset=utf-8')
435
- @request.log_response res
436
- log[0].should eq "# => 200 OK | text/html 4 bytes\n"
687
+ res = res_double(code: '200', class: Net::HTTPOK, body: 'abcd')
688
+ allow(res).to receive(:[]).with('Content-type').and_return('text/html; charset=utf-8')
689
+ response = response_from_res_double(res, @request)
690
+ response.log_response
691
+ expect(log).to eq ["# => 200 OK | text/html 4 bytes, 1.00s\n"]
437
692
  end
438
693
 
439
694
  describe "timeout" do
440
695
  it "does not set timeouts if not specified" do
441
696
  @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
442
- @http.stub(:request)
443
- @request.stub(:process_result)
444
- @request.stub(:response_log)
697
+ allow(@http).to receive(:request)
698
+ allow(@request).to receive(:process_result)
699
+ allow(@request).to receive(:response_log)
445
700
 
446
- @net.should_not_receive(:read_timeout=)
447
- @net.should_not_receive(:open_timeout=)
701
+ expect(@net).not_to receive(:read_timeout=)
702
+ expect(@net).not_to receive(:open_timeout=)
448
703
 
449
- @request.transmit(@uri, 'req', nil)
704
+ @request.send(:transmit, @uri, 'req', nil)
450
705
  end
451
706
 
452
- it "set read_timeout" do
453
- @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123)
454
- @http.stub(:request)
455
- @request.stub(:process_result)
456
- @request.stub(:response_log)
707
+ it 'sets read_timeout' do
708
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :read_timeout => 123)
709
+ allow(@http).to receive(:request)
710
+ allow(@request).to receive(:process_result)
711
+ allow(@request).to receive(:response_log)
457
712
 
458
- @net.should_receive(:read_timeout=).with(123)
713
+ expect(@net).to receive(:read_timeout=).with(123)
459
714
 
460
- @request.transmit(@uri, 'req', nil)
715
+ @request.send(:transmit, @uri, 'req', nil)
461
716
  end
462
717
 
463
- it "set open_timeout" do
718
+ it "sets open_timeout" do
464
719
  @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :open_timeout => 123)
465
- @http.stub(:request)
466
- @request.stub(:process_result)
467
- @request.stub(:response_log)
720
+ allow(@http).to receive(:request)
721
+ allow(@request).to receive(:process_result)
722
+ allow(@request).to receive(:response_log)
468
723
 
469
- @net.should_receive(:open_timeout=).with(123)
724
+ expect(@net).to receive(:open_timeout=).with(123)
470
725
 
471
- @request.transmit(@uri, 'req', nil)
726
+ @request.send(:transmit, @uri, 'req', nil)
472
727
  end
473
728
 
729
+ it 'sets both timeouts with :timeout' do
730
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123)
731
+ allow(@http).to receive(:request)
732
+ allow(@request).to receive(:process_result)
733
+ allow(@request).to receive(:response_log)
734
+
735
+ expect(@net).to receive(:open_timeout=).with(123)
736
+ expect(@net).to receive(:read_timeout=).with(123)
737
+
738
+ @request.send(:transmit, @uri, 'req', nil)
739
+ end
740
+
741
+ it 'supersedes :timeout with open/read_timeout' do
742
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123, :open_timeout => 34, :read_timeout => 56)
743
+ allow(@http).to receive(:request)
744
+ allow(@request).to receive(:process_result)
745
+ allow(@request).to receive(:response_log)
746
+
747
+ expect(@net).to receive(:open_timeout=).with(34)
748
+ expect(@net).to receive(:read_timeout=).with(56)
749
+
750
+ @request.send(:transmit, @uri, 'req', nil)
751
+ end
752
+
753
+
474
754
  it "disable timeout by setting it to nil" do
475
- @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => nil, :open_timeout => nil)
476
- @http.stub(:request)
477
- @request.stub(:process_result)
478
- @request.stub(:response_log)
755
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :read_timeout => nil, :open_timeout => nil)
756
+ allow(@http).to receive(:request)
757
+ allow(@request).to receive(:process_result)
758
+ allow(@request).to receive(:response_log)
479
759
 
480
- @net.should_receive(:read_timeout=).with(nil)
481
- @net.should_receive(:open_timeout=).with(nil)
760
+ expect(@net).to receive(:read_timeout=).with(nil)
761
+ expect(@net).to receive(:open_timeout=).with(nil)
482
762
 
483
- @request.transmit(@uri, 'req', nil)
763
+ @request.send(:transmit, @uri, 'req', nil)
764
+ end
765
+
766
+ it 'deprecated: warns when disabling timeout by setting it to -1' do
767
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :read_timeout => -1)
768
+ allow(@http).to receive(:request)
769
+ allow(@request).to receive(:process_result)
770
+ allow(@request).to receive(:response_log)
771
+
772
+ expect(@net).to receive(:read_timeout=).with(nil)
773
+
774
+ expect(fake_stderr {
775
+ @request.send(:transmit, @uri, 'req', nil)
776
+ }).to match(/^Deprecated: .*timeout.* nil instead of -1$/)
484
777
  end
485
778
 
486
779
  it "deprecated: disable timeout by setting it to -1" do
487
- @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => -1, :open_timeout => -1)
488
- @http.stub(:request)
489
- @request.stub(:process_result)
490
- @request.stub(:response_log)
780
+ @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :read_timeout => -1, :open_timeout => -1)
781
+ allow(@http).to receive(:request)
782
+ allow(@request).to receive(:process_result)
783
+ allow(@request).to receive(:response_log)
491
784
 
492
- @request.should_receive(:warn)
493
- @net.should_receive(:read_timeout=).with(nil)
785
+ expect(@request).to receive(:warn)
786
+ expect(@net).to receive(:read_timeout=).with(nil)
494
787
 
495
- @request.should_receive(:warn)
496
- @net.should_receive(:open_timeout=).with(nil)
788
+ expect(@request).to receive(:warn)
789
+ expect(@net).to receive(:open_timeout=).with(nil)
497
790
 
498
- @request.transmit(@uri, 'req', nil)
791
+ @request.send(:transmit, @uri, 'req', nil)
499
792
  end
500
793
  end
501
794
 
502
795
  describe "ssl" do
503
796
  it "uses SSL when the URI refers to a https address" do
504
- @uri.stub(:is_a?).with(URI::HTTPS).and_return(true)
505
- @net.should_receive(:use_ssl=).with(true)
506
- @http.stub(:request)
507
- @request.stub(:process_result)
508
- @request.stub(:response_log)
509
- @request.transmit(@uri, 'req', 'payload')
797
+ allow(@uri).to receive(:is_a?).with(URI::HTTPS).and_return(true)
798
+ expect(@net).to receive(:use_ssl=).with(true)
799
+ allow(@http).to receive(:request)
800
+ allow(@request).to receive(:process_result)
801
+ allow(@request).to receive(:response_log)
802
+ @request.send(:transmit, @uri, 'req', 'payload')
510
803
  end
511
804
 
512
805
  it "should default to verifying ssl certificates" do
513
- @request.verify_ssl.should eq OpenSSL::SSL::VERIFY_PEER
806
+ expect(@request.verify_ssl).to eq OpenSSL::SSL::VERIFY_PEER
514
807
  end
515
808
 
516
809
  it "should have expected values for VERIFY_PEER and VERIFY_NONE" do
517
- OpenSSL::SSL::VERIFY_NONE.should eq(0)
518
- OpenSSL::SSL::VERIFY_PEER.should eq(1)
810
+ expect(OpenSSL::SSL::VERIFY_NONE).to eq(0)
811
+ expect(OpenSSL::SSL::VERIFY_PEER).to eq(1)
519
812
  end
520
813
 
521
814
  it "should set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is false" do
522
815
  @request = RestClient::Request.new(:method => :put, :verify_ssl => false, :url => 'http://some/resource', :payload => 'payload')
523
- @net.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
524
- @http.stub(:request)
525
- @request.stub(:process_result)
526
- @request.stub(:response_log)
527
- @request.transmit(@uri, 'req', 'payload')
816
+ expect(@net).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
817
+ allow(@http).to receive(:request)
818
+ allow(@request).to receive(:process_result)
819
+ allow(@request).to receive(:response_log)
820
+ @request.send(:transmit, @uri, 'req', 'payload')
528
821
  end
529
822
 
530
823
  it "should not set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is true" do
531
824
  @request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload', :verify_ssl => true)
532
- @net.should_not_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
533
- @http.stub(:request)
534
- @request.stub(:process_result)
535
- @request.stub(:response_log)
536
- @request.transmit(@uri, 'req', 'payload')
825
+ expect(@net).not_to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
826
+ allow(@http).to receive(:request)
827
+ allow(@request).to receive(:process_result)
828
+ allow(@request).to receive(:response_log)
829
+ @request.send(:transmit, @uri, 'req', 'payload')
537
830
  end
538
831
 
539
832
  it "should set net.verify_mode to OpenSSL::SSL::VERIFY_PEER if verify_ssl is true" do
540
833
  @request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload', :verify_ssl => true)
541
- @net.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
542
- @http.stub(:request)
543
- @request.stub(:process_result)
544
- @request.stub(:response_log)
545
- @request.transmit(@uri, 'req', 'payload')
834
+ expect(@net).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
835
+ allow(@http).to receive(:request)
836
+ allow(@request).to receive(:process_result)
837
+ allow(@request).to receive(:response_log)
838
+ @request.send(:transmit, @uri, 'req', 'payload')
546
839
  end
547
840
 
548
841
  it "should set net.verify_mode to OpenSSL::SSL::VERIFY_PEER if verify_ssl is not given" do
549
842
  @request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload')
550
- @net.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
551
- @http.stub(:request)
552
- @request.stub(:process_result)
553
- @request.stub(:response_log)
554
- @request.transmit(@uri, 'req', 'payload')
843
+ expect(@net).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
844
+ allow(@http).to receive(:request)
845
+ allow(@request).to receive(:process_result)
846
+ allow(@request).to receive(:response_log)
847
+ @request.send(:transmit, @uri, 'req', 'payload')
555
848
  end
556
849
 
557
850
  it "should set net.verify_mode to the passed value if verify_ssl is an OpenSSL constant" do
@@ -560,15 +853,15 @@ describe RestClient::Request do
560
853
  :url => 'https://some/resource',
561
854
  :payload => 'payload',
562
855
  :verify_ssl => mode )
563
- @net.should_receive(:verify_mode=).with(mode)
564
- @http.stub(:request)
565
- @request.stub(:process_result)
566
- @request.stub(:response_log)
567
- @request.transmit(@uri, 'req', 'payload')
856
+ expect(@net).to receive(:verify_mode=).with(mode)
857
+ allow(@http).to receive(:request)
858
+ allow(@request).to receive(:process_result)
859
+ allow(@request).to receive(:response_log)
860
+ @request.send(:transmit, @uri, 'req', 'payload')
568
861
  end
569
862
 
570
863
  it "should default to not having an ssl_client_cert" do
571
- @request.ssl_client_cert.should be(nil)
864
+ expect(@request.ssl_client_cert).to be(nil)
572
865
  end
573
866
 
574
867
  it "should set the ssl_version if provided" do
@@ -578,11 +871,11 @@ describe RestClient::Request do
578
871
  :payload => 'payload',
579
872
  :ssl_version => "TLSv1"
580
873
  )
581
- @net.should_receive(:ssl_version=).with("TLSv1")
582
- @http.stub(:request)
583
- @request.stub(:process_result)
584
- @request.stub(:response_log)
585
- @request.transmit(@uri, 'req', 'payload')
874
+ expect(@net).to receive(:ssl_version=).with("TLSv1")
875
+ allow(@http).to receive(:request)
876
+ allow(@request).to receive(:process_result)
877
+ allow(@request).to receive(:response_log)
878
+ @request.send(:transmit, @uri, 'req', 'payload')
586
879
  end
587
880
 
588
881
  it "should not set the ssl_version if not provided" do
@@ -591,11 +884,11 @@ describe RestClient::Request do
591
884
  :url => 'https://some/resource',
592
885
  :payload => 'payload'
593
886
  )
594
- @net.should_not_receive(:ssl_version=).with("TLSv1")
595
- @http.stub(:request)
596
- @request.stub(:process_result)
597
- @request.stub(:response_log)
598
- @request.transmit(@uri, 'req', 'payload')
887
+ expect(@net).not_to receive(:ssl_version=).with("TLSv1")
888
+ allow(@http).to receive(:request)
889
+ allow(@request).to receive(:process_result)
890
+ allow(@request).to receive(:response_log)
891
+ @request.send(:transmit, @uri, 'req', 'payload')
599
892
  end
600
893
 
601
894
  it "should set the ssl_ciphers if provided" do
@@ -606,11 +899,11 @@ describe RestClient::Request do
606
899
  :payload => 'payload',
607
900
  :ssl_ciphers => ciphers
608
901
  )
609
- @net.should_receive(:ciphers=).with(ciphers)
610
- @http.stub(:request)
611
- @request.stub(:process_result)
612
- @request.stub(:response_log)
613
- @request.transmit(@uri, 'req', 'payload')
902
+ expect(@net).to receive(:ciphers=).with(ciphers)
903
+ allow(@http).to receive(:request)
904
+ allow(@request).to receive(:process_result)
905
+ allow(@request).to receive(:response_log)
906
+ @request.send(:transmit, @uri, 'req', 'payload')
614
907
  end
615
908
 
616
909
  it "should not set the ssl_ciphers if set to nil" do
@@ -620,61 +913,11 @@ describe RestClient::Request do
620
913
  :payload => 'payload',
621
914
  :ssl_ciphers => nil,
622
915
  )
623
- @net.should_not_receive(:ciphers=)
624
- @http.stub(:request)
625
- @request.stub(:process_result)
626
- @request.stub(:response_log)
627
- @request.transmit(@uri, 'req', 'payload')
628
- end
629
-
630
- it "should override ssl_ciphers with better defaults with weak default ciphers" do
631
- stub_const(
632
- '::OpenSSL::SSL::SSLContext::DEFAULT_PARAMS',
633
- {
634
- :ssl_version=>"SSLv23",
635
- :verify_mode=>1,
636
- :ciphers=>"ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
637
- :options=>-2147480577,
638
- }
639
- )
640
-
641
- @request = RestClient::Request.new(
642
- :method => :put,
643
- :url => 'https://some/resource',
644
- :payload => 'payload',
645
- )
646
-
647
- @net.should_receive(:ciphers=).with(RestClient::Request::DefaultCiphers)
648
-
649
- @http.stub(:request)
650
- @request.stub(:process_result)
651
- @request.stub(:response_log)
652
- @request.transmit(@uri, 'req', 'payload')
653
- end
654
-
655
- it "should not override ssl_ciphers with better defaults with different default ciphers" do
656
- stub_const(
657
- '::OpenSSL::SSL::SSLContext::DEFAULT_PARAMS',
658
- {
659
- :ssl_version=>"SSLv23",
660
- :verify_mode=>1,
661
- :ciphers=>"HIGH:!aNULL:!eNULL:!EXPORT:!LOW:!MEDIUM:!SSLv2",
662
- :options=>-2147480577,
663
- }
664
- )
665
-
666
- @request = RestClient::Request.new(
667
- :method => :put,
668
- :url => 'https://some/resource',
669
- :payload => 'payload',
670
- )
671
-
672
- @net.should_not_receive(:ciphers=)
673
-
674
- @http.stub(:request)
675
- @request.stub(:process_result)
676
- @request.stub(:response_log)
677
- @request.transmit(@uri, 'req', 'payload')
916
+ expect(@net).not_to receive(:ciphers=)
917
+ allow(@http).to receive(:request)
918
+ allow(@request).to receive(:process_result)
919
+ allow(@request).to receive(:response_log)
920
+ @request.send(:transmit, @uri, 'req', 'payload')
678
921
  end
679
922
 
680
923
  it "should set the ssl_client_cert if provided" do
@@ -684,11 +927,11 @@ describe RestClient::Request do
684
927
  :payload => 'payload',
685
928
  :ssl_client_cert => "whatsupdoc!"
686
929
  )
687
- @net.should_receive(:cert=).with("whatsupdoc!")
688
- @http.stub(:request)
689
- @request.stub(:process_result)
690
- @request.stub(:response_log)
691
- @request.transmit(@uri, 'req', 'payload')
930
+ expect(@net).to receive(:cert=).with("whatsupdoc!")
931
+ allow(@http).to receive(:request)
932
+ allow(@request).to receive(:process_result)
933
+ allow(@request).to receive(:response_log)
934
+ @request.send(:transmit, @uri, 'req', 'payload')
692
935
  end
693
936
 
694
937
  it "should not set the ssl_client_cert if it is not provided" do
@@ -697,15 +940,15 @@ describe RestClient::Request do
697
940
  :url => 'https://some/resource',
698
941
  :payload => 'payload'
699
942
  )
700
- @net.should_not_receive(:cert=)
701
- @http.stub(:request)
702
- @request.stub(:process_result)
703
- @request.stub(:response_log)
704
- @request.transmit(@uri, 'req', 'payload')
943
+ expect(@net).not_to receive(:cert=)
944
+ allow(@http).to receive(:request)
945
+ allow(@request).to receive(:process_result)
946
+ allow(@request).to receive(:response_log)
947
+ @request.send(:transmit, @uri, 'req', 'payload')
705
948
  end
706
949
 
707
950
  it "should default to not having an ssl_client_key" do
708
- @request.ssl_client_key.should be(nil)
951
+ expect(@request.ssl_client_key).to be(nil)
709
952
  end
710
953
 
711
954
  it "should set the ssl_client_key if provided" do
@@ -715,11 +958,11 @@ describe RestClient::Request do
715
958
  :payload => 'payload',
716
959
  :ssl_client_key => "whatsupdoc!"
717
960
  )
718
- @net.should_receive(:key=).with("whatsupdoc!")
719
- @http.stub(:request)
720
- @request.stub(:process_result)
721
- @request.stub(:response_log)
722
- @request.transmit(@uri, 'req', 'payload')
961
+ expect(@net).to receive(:key=).with("whatsupdoc!")
962
+ allow(@http).to receive(:request)
963
+ allow(@request).to receive(:process_result)
964
+ allow(@request).to receive(:response_log)
965
+ @request.send(:transmit, @uri, 'req', 'payload')
723
966
  end
724
967
 
725
968
  it "should not set the ssl_client_key if it is not provided" do
@@ -728,15 +971,15 @@ describe RestClient::Request do
728
971
  :url => 'https://some/resource',
729
972
  :payload => 'payload'
730
973
  )
731
- @net.should_not_receive(:key=)
732
- @http.stub(:request)
733
- @request.stub(:process_result)
734
- @request.stub(:response_log)
735
- @request.transmit(@uri, 'req', 'payload')
974
+ expect(@net).not_to receive(:key=)
975
+ allow(@http).to receive(:request)
976
+ allow(@request).to receive(:process_result)
977
+ allow(@request).to receive(:response_log)
978
+ @request.send(:transmit, @uri, 'req', 'payload')
736
979
  end
737
980
 
738
981
  it "should default to not having an ssl_ca_file" do
739
- @request.ssl_ca_file.should be(nil)
982
+ expect(@request.ssl_ca_file).to be(nil)
740
983
  end
741
984
 
742
985
  it "should set the ssl_ca_file if provided" do
@@ -746,12 +989,12 @@ describe RestClient::Request do
746
989
  :payload => 'payload',
747
990
  :ssl_ca_file => "Certificate Authority File"
748
991
  )
749
- @net.should_receive(:ca_file=).with("Certificate Authority File")
750
- @net.should_not_receive(:cert_store=)
751
- @http.stub(:request)
752
- @request.stub(:process_result)
753
- @request.stub(:response_log)
754
- @request.transmit(@uri, 'req', 'payload')
992
+ expect(@net).to receive(:ca_file=).with("Certificate Authority File")
993
+ expect(@net).not_to receive(:cert_store=)
994
+ allow(@http).to receive(:request)
995
+ allow(@request).to receive(:process_result)
996
+ allow(@request).to receive(:response_log)
997
+ @request.send(:transmit, @uri, 'req', 'payload')
755
998
  end
756
999
 
757
1000
  it "should not set the ssl_ca_file if it is not provided" do
@@ -760,15 +1003,15 @@ describe RestClient::Request do
760
1003
  :url => 'https://some/resource',
761
1004
  :payload => 'payload'
762
1005
  )
763
- @net.should_not_receive(:ca_file=)
764
- @http.stub(:request)
765
- @request.stub(:process_result)
766
- @request.stub(:response_log)
767
- @request.transmit(@uri, 'req', 'payload')
1006
+ expect(@net).not_to receive(:ca_file=)
1007
+ allow(@http).to receive(:request)
1008
+ allow(@request).to receive(:process_result)
1009
+ allow(@request).to receive(:response_log)
1010
+ @request.send(:transmit, @uri, 'req', 'payload')
768
1011
  end
769
1012
 
770
1013
  it "should default to not having an ssl_ca_path" do
771
- @request.ssl_ca_path.should be(nil)
1014
+ expect(@request.ssl_ca_path).to be(nil)
772
1015
  end
773
1016
 
774
1017
  it "should set the ssl_ca_path if provided" do
@@ -778,12 +1021,12 @@ describe RestClient::Request do
778
1021
  :payload => 'payload',
779
1022
  :ssl_ca_path => "Certificate Authority Path"
780
1023
  )
781
- @net.should_receive(:ca_path=).with("Certificate Authority Path")
782
- @net.should_not_receive(:cert_store=)
783
- @http.stub(:request)
784
- @request.stub(:process_result)
785
- @request.stub(:response_log)
786
- @request.transmit(@uri, 'req', 'payload')
1024
+ expect(@net).to receive(:ca_path=).with("Certificate Authority Path")
1025
+ expect(@net).not_to receive(:cert_store=)
1026
+ allow(@http).to receive(:request)
1027
+ allow(@request).to receive(:process_result)
1028
+ allow(@request).to receive(:response_log)
1029
+ @request.send(:transmit, @uri, 'req', 'payload')
787
1030
  end
788
1031
 
789
1032
  it "should not set the ssl_ca_path if it is not provided" do
@@ -792,11 +1035,11 @@ describe RestClient::Request do
792
1035
  :url => 'https://some/resource',
793
1036
  :payload => 'payload'
794
1037
  )
795
- @net.should_not_receive(:ca_path=)
796
- @http.stub(:request)
797
- @request.stub(:process_result)
798
- @request.stub(:response_log)
799
- @request.transmit(@uri, 'req', 'payload')
1038
+ expect(@net).not_to receive(:ca_path=)
1039
+ allow(@http).to receive(:request)
1040
+ allow(@request).to receive(:process_result)
1041
+ allow(@request).to receive(:response_log)
1042
+ @request.send(:transmit, @uri, 'req', 'payload')
800
1043
  end
801
1044
 
802
1045
  it "should set the ssl_cert_store if provided" do
@@ -809,13 +1052,13 @@ describe RestClient::Request do
809
1052
  :payload => 'payload',
810
1053
  :ssl_cert_store => store
811
1054
  )
812
- @net.should_receive(:cert_store=).with(store)
813
- @net.should_not_receive(:ca_path=)
814
- @net.should_not_receive(:ca_file=)
815
- @http.stub(:request)
816
- @request.stub(:process_result)
817
- @request.stub(:response_log)
818
- @request.transmit(@uri, 'req', 'payload')
1055
+ expect(@net).to receive(:cert_store=).with(store)
1056
+ expect(@net).not_to receive(:ca_path=)
1057
+ expect(@net).not_to receive(:ca_file=)
1058
+ allow(@http).to receive(:request)
1059
+ allow(@request).to receive(:process_result)
1060
+ allow(@request).to receive(:response_log)
1061
+ @request.send(:transmit, @uri, 'req', 'payload')
819
1062
  end
820
1063
 
821
1064
  it "should by default set the ssl_cert_store if no CA info is provided" do
@@ -824,13 +1067,13 @@ describe RestClient::Request do
824
1067
  :url => 'https://some/resource',
825
1068
  :payload => 'payload'
826
1069
  )
827
- @net.should_receive(:cert_store=)
828
- @net.should_not_receive(:ca_path=)
829
- @net.should_not_receive(:ca_file=)
830
- @http.stub(:request)
831
- @request.stub(:process_result)
832
- @request.stub(:response_log)
833
- @request.transmit(@uri, 'req', 'payload')
1070
+ expect(@net).to receive(:cert_store=)
1071
+ expect(@net).not_to receive(:ca_path=)
1072
+ expect(@net).not_to receive(:ca_file=)
1073
+ allow(@http).to receive(:request)
1074
+ allow(@request).to receive(:process_result)
1075
+ allow(@request).to receive(:response_log)
1076
+ @request.send(:transmit, @uri, 'req', 'payload')
834
1077
  end
835
1078
 
836
1079
  it "should not set the ssl_cert_store if it is set falsy" do
@@ -840,11 +1083,11 @@ describe RestClient::Request do
840
1083
  :payload => 'payload',
841
1084
  :ssl_cert_store => nil,
842
1085
  )
843
- @net.should_not_receive(:cert_store=)
844
- @http.stub(:request)
845
- @request.stub(:process_result)
846
- @request.stub(:response_log)
847
- @request.transmit(@uri, 'req', 'payload')
1086
+ expect(@net).not_to receive(:cert_store=)
1087
+ allow(@http).to receive(:request)
1088
+ allow(@request).to receive(:process_result)
1089
+ allow(@request).to receive(:response_log)
1090
+ @request.send(:transmit, @uri, 'req', 'payload')
848
1091
  end
849
1092
 
850
1093
  it "should not set the ssl_verify_callback by default" do
@@ -853,11 +1096,11 @@ describe RestClient::Request do
853
1096
  :url => 'https://some/resource',
854
1097
  :payload => 'payload',
855
1098
  )
856
- @net.should_not_receive(:verify_callback=)
857
- @http.stub(:request)
858
- @request.stub(:process_result)
859
- @request.stub(:response_log)
860
- @request.transmit(@uri, 'req', 'payload')
1099
+ expect(@net).not_to receive(:verify_callback=)
1100
+ allow(@http).to receive(:request)
1101
+ allow(@request).to receive(:process_result)
1102
+ allow(@request).to receive(:response_log)
1103
+ @request.send(:transmit, @uri, 'req', 'payload')
861
1104
  end
862
1105
 
863
1106
  it "should set the ssl_verify_callback if passed" do
@@ -868,7 +1111,7 @@ describe RestClient::Request do
868
1111
  :payload => 'payload',
869
1112
  :ssl_verify_callback => callback,
870
1113
  )
871
- @net.should_receive(:verify_callback=).with(callback)
1114
+ expect(@net).to receive(:verify_callback=).with(callback)
872
1115
 
873
1116
  # we'll read cert_store on jruby
874
1117
  # https://github.com/jruby/jruby/issues/597
@@ -876,10 +1119,10 @@ describe RestClient::Request do
876
1119
  allow(@net).to receive(:cert_store)
877
1120
  end
878
1121
 
879
- @http.stub(:request)
880
- @request.stub(:process_result)
881
- @request.stub(:response_log)
882
- @request.transmit(@uri, 'req', 'payload')
1122
+ allow(@http).to receive(:request)
1123
+ allow(@request).to receive(:process_result)
1124
+ allow(@request).to receive(:response_log)
1125
+ @request.send(:transmit, @uri, 'req', 'payload')
883
1126
  end
884
1127
 
885
1128
  # </ssl>
@@ -892,11 +1135,11 @@ describe RestClient::Request do
892
1135
  :payload => 'payload'
893
1136
  )
894
1137
  net_http_res = Net::HTTPNoContent.new("", "204", "No Content")
895
- net_http_res.stub(:read_body).and_return(nil)
896
- @http.should_receive(:request).and_return(@request.fetch_body(net_http_res))
897
- response = @request.transmit(@uri, 'req', 'payload')
898
- response.should_not be_nil
899
- response.code.should eq 204
1138
+ allow(net_http_res).to receive(:read_body).and_return(nil)
1139
+ expect(@http).to receive(:request).and_return(net_http_res)
1140
+ response = @request.send(:transmit, @uri, 'req', 'payload')
1141
+ expect(response).not_to be_nil
1142
+ expect(response.code).to eq 204
900
1143
  end
901
1144
 
902
1145
  describe "raw response" do
@@ -904,14 +1147,92 @@ describe RestClient::Request do
904
1147
  @request = RestClient::Request.new(:method => "get", :url => "example.com", :raw_response => true)
905
1148
 
906
1149
  tempfile = double("tempfile")
907
- tempfile.should_receive(:binmode)
908
- tempfile.stub(:open)
909
- tempfile.stub(:close)
910
- Tempfile.should_receive(:new).with("rest-client").and_return(tempfile)
1150
+ expect(tempfile).to receive(:binmode)
1151
+ allow(tempfile).to receive(:open)
1152
+ allow(tempfile).to receive(:close)
1153
+ expect(Tempfile).to receive(:new).with("rest-client.").and_return(tempfile)
911
1154
 
912
1155
  net_http_res = Net::HTTPOK.new(nil, "200", "body")
913
- net_http_res.stub(:read_body).and_return("body")
914
- @request.fetch_body(net_http_res)
1156
+ allow(net_http_res).to receive(:read_body).and_return("body")
1157
+ received_tempfile = @request.send(:fetch_body_to_tempfile, net_http_res)
1158
+ expect(received_tempfile).to eq tempfile
1159
+ end
1160
+ end
1161
+
1162
+ describe 'payloads' do
1163
+ it 'should accept string payloads' do
1164
+ payload = 'Foo'
1165
+ @request = RestClient::Request.new(method: :get, url: 'example.com', :payload => payload)
1166
+ expect(@request).to receive(:process_result)
1167
+ expect(@http).to receive(:request).with('req', payload)
1168
+ @request.send(:transmit, @uri, 'req', payload)
1169
+ end
1170
+
1171
+ it 'should accept streaming IO payloads' do
1172
+ payload = StringIO.new('streamed')
1173
+
1174
+ @request = RestClient::Request.new(method: :get, url: 'example.com', :payload => payload)
1175
+ expect(@request).to receive(:process_result)
1176
+
1177
+ @get = double('net::http::get')
1178
+ expect(@get).to receive(:body_stream=).with(instance_of(RestClient::Payload::Streamed))
1179
+
1180
+ allow(@request.net_http_request_class(:GET)).to receive(:new).and_return(@get)
1181
+ expect(@http).to receive(:request).with(@get, nil)
1182
+ @request.execute
1183
+ end
1184
+ end
1185
+
1186
+ describe 'constructor' do
1187
+ it 'should reject valid URIs with no hostname' do
1188
+ expect(URI.parse('http:///').hostname).to be_nil
1189
+
1190
+ expect {
1191
+ RestClient::Request.new(method: :get, url: 'http:///')
1192
+ }.to raise_error(URI::InvalidURIError, /\Abad URI/)
1193
+ end
1194
+
1195
+ it 'should reject invalid URIs' do
1196
+ expect {
1197
+ RestClient::Request.new(method: :get, url: 'http://::')
1198
+ }.to raise_error(URI::InvalidURIError)
1199
+ end
1200
+ end
1201
+
1202
+ describe 'process_url_params' do
1203
+ it 'should handle basic URL params' do
1204
+ expect(@request.process_url_params('https://example.com/foo', params: {key1: 123, key2: 'abc'})).
1205
+ to eq 'https://example.com/foo?key1=123&key2=abc'
1206
+
1207
+ expect(@request.process_url_params('https://example.com/foo', params: {'key1' => 123})).
1208
+ to eq 'https://example.com/foo?key1=123'
1209
+
1210
+ expect(@request.process_url_params('https://example.com/path',
1211
+ params: {foo: 'one two', bar: 'three + four == seven'})).
1212
+ to eq 'https://example.com/path?foo=one+two&bar=three+%2B+four+%3D%3D+seven'
1213
+ end
1214
+
1215
+ it 'should combine with & when URL params already exist' do
1216
+ expect(@request.process_url_params('https://example.com/path?foo=1', params: {bar: 2})).
1217
+ to eq 'https://example.com/path?foo=1&bar=2'
1218
+ end
1219
+
1220
+ it 'should handle complex nested URL params per Rack / Rails conventions' do
1221
+ expect(@request.process_url_params('https://example.com/', params: {
1222
+ foo: [1,2,3],
1223
+ null: nil,
1224
+ falsy: false,
1225
+ math: '2+2=4',
1226
+ nested: {'key + escaped' => 'value + escaped', other: [], arr: [1,2]},
1227
+ })).to eq 'https://example.com/?foo[]=1&foo[]=2&foo[]=3&null&falsy=false&math=2%2B2%3D4' \
1228
+ '&nested[key+%2B+escaped]=value+%2B+escaped&nested[other]' \
1229
+ '&nested[arr][]=1&nested[arr][]=2'
1230
+ end
1231
+
1232
+ it 'should handle ParamsArray objects' do
1233
+ expect(@request.process_url_params('https://example.com/',
1234
+ params: RestClient::ParamsArray.new([[:foo, 1], [:foo, 2]])
1235
+ )).to eq 'https://example.com/?foo=1&foo=2'
915
1236
  end
916
1237
  end
917
1238
  end