rest-client 1.7.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.mailmap +10 -0
- data/.rspec +2 -1
- data/.rubocop +2 -0
- data/.rubocop-disables.yml +386 -0
- data/.rubocop.yml +8 -0
- data/.travis.yml +56 -8
- data/AUTHORS +26 -1
- data/README.md +901 -0
- data/Rakefile +27 -3
- data/bin/restclient +3 -5
- data/history.md +199 -0
- data/lib/restclient/abstract_response.rb +196 -50
- data/lib/restclient/exceptions.rb +96 -55
- data/lib/restclient/params_array.rb +72 -0
- data/lib/restclient/payload.rb +70 -74
- data/lib/restclient/platform.rb +20 -1
- data/lib/restclient/raw_response.rb +21 -6
- data/lib/restclient/request.rb +572 -284
- data/lib/restclient/resource.rb +19 -9
- data/lib/restclient/response.rb +75 -9
- data/lib/restclient/utils.rb +274 -0
- data/lib/restclient/version.rb +2 -1
- data/lib/restclient.rb +21 -3
- data/rest-client.gemspec +13 -10
- data/spec/ISS.jpg +0 -0
- data/spec/helpers.rb +54 -0
- data/spec/integration/_lib.rb +1 -0
- data/spec/integration/capath_digicert/3513523f.0 +22 -0
- data/spec/integration/capath_digicert/399e7759.0 +22 -0
- data/spec/integration/capath_digicert/digicert.crt +20 -17
- data/spec/integration/certs/digicert.crt +20 -17
- data/spec/integration/httpbin_spec.rb +128 -0
- data/spec/integration/integration_spec.rb +97 -14
- data/spec/integration/request_spec.rb +29 -6
- data/spec/spec_helper.rb +28 -1
- data/spec/unit/_lib.rb +1 -0
- data/spec/unit/abstract_response_spec.rb +95 -35
- data/spec/unit/exceptions_spec.rb +41 -28
- data/spec/unit/params_array_spec.rb +36 -0
- data/spec/unit/payload_spec.rb +118 -68
- data/spec/unit/raw_response_spec.rb +10 -5
- data/spec/unit/request2_spec.rb +34 -12
- data/spec/unit/request_spec.rb +751 -418
- data/spec/unit/resource_spec.rb +31 -27
- data/spec/unit/response_spec.rb +144 -58
- data/spec/unit/restclient_spec.rb +16 -15
- data/spec/unit/utils_spec.rb +147 -0
- data/spec/unit/windows/root_certs_spec.rb +3 -3
- metadata +121 -70
- data/README.rdoc +0 -324
- data/spec/integration/capath_digicert/244b5494.0 +0 -19
- data/spec/integration/capath_digicert/81b9768f.0 +0 -19
- data/spec/unit/master_shake.jpg +0 -0
data/spec/unit/request_spec.rb
CHANGED
@@ -1,120 +1,206 @@
|
|
1
|
-
|
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.
|
9
|
-
@uri.
|
10
|
-
@uri.
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@net.
|
18
|
-
@net.
|
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
|
25
|
-
@request.default_headers[:accept].
|
26
|
+
it "accept */* mimetype" do
|
27
|
+
expect(@request.default_headers[:accept]).to eq '*/*'
|
26
28
|
end
|
27
29
|
|
28
|
-
|
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
|
-
|
31
|
-
|
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
|
-
|
35
|
-
|
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
|
-
|
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
|
44
|
-
|
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
|
48
|
-
|
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
|
-
|
53
|
-
|
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
69
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
84
|
-
@request.
|
85
|
-
@request.
|
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
|
-
|
91
|
-
@request.
|
92
|
-
@request.
|
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
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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.
|
117
|
-
@request.make_headers({}).
|
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
|
-
['
|
128
|
-
|
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
|
-
}.
|
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
|
-
[
|
140
|
-
|
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
|
-
}.
|
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
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
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
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
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).
|
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.
|
294
|
+
expect(@request).to receive(:default_headers).and_return({:accept => '*/*'})
|
170
295
|
headers = @request.make_headers("Accept" => "application/json", :accept_encoding => 'gzip')
|
171
|
-
headers.
|
172
|
-
headers["Accept-Encoding"].
|
173
|
-
headers.
|
174
|
-
headers["Accept"].
|
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.
|
303
|
+
expect(@request).to receive(:default_headers).and_return({ '1' => '2' })
|
179
304
|
headers = @request.make_headers('1' => '3')
|
180
|
-
headers.
|
181
|
-
headers['1'].
|
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.
|
310
|
+
expect(@request).to receive(:default_headers).and_return({ '1' => '2' })
|
186
311
|
headers = @request.make_headers('1' => 3)
|
187
|
-
headers.
|
188
|
-
headers['1'].
|
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.
|
320
|
+
expect(@request).to receive(:default_headers).and_return({})
|
196
321
|
headers = @request.make_headers(:content_type => 'abc')
|
197
|
-
headers.
|
198
|
-
headers['Content-Type'].
|
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.
|
327
|
+
expect(@request).to receive(:default_headers).and_return({})
|
203
328
|
headers = @request.make_headers(:content_type => 'json')
|
204
|
-
headers.
|
205
|
-
headers['Content-Type'].
|
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.
|
334
|
+
expect(@request).to receive(:default_headers).and_return({})
|
210
335
|
headers = @request.make_headers(:accept => 'json, mp3')
|
211
|
-
headers.
|
212
|
-
headers['Accept'].
|
336
|
+
expect(headers).to have_key('Accept')
|
337
|
+
expect(headers['Accept']).to eq 'application/json, audio/mpeg'
|
213
338
|
|
214
|
-
@request.
|
339
|
+
expect(@request).to receive(:default_headers).and_return({})
|
215
340
|
headers = @request.make_headers(:accept => :json)
|
216
|
-
headers.
|
217
|
-
headers['Accept'].
|
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.
|
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'].
|
224
|
-
headers['bar_bar'].
|
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'].
|
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.
|
236
|
-
klass.
|
237
|
-
@request.
|
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.
|
243
|
-
@request.
|
244
|
-
@request.transmit
|
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.
|
250
|
-
@request.
|
251
|
-
@request.
|
252
|
-
@request.transmit
|
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
|
-
|
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
|
-
|
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 =
|
265
|
-
payload.
|
266
|
-
payload.
|
267
|
-
payload.
|
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
|
-
|
273
|
-
|
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.
|
423
|
+
allow(@http).to receive(:request)
|
279
424
|
|
280
|
-
@request.
|
281
|
-
@request.
|
425
|
+
allow(@request).to receive(:process_result)
|
426
|
+
allow(@request).to receive(:response_log)
|
282
427
|
|
283
|
-
@request.
|
284
|
-
@request.
|
285
|
-
@request.
|
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
|
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.
|
436
|
+
allow(@request).to receive(:user).and_return(nil)
|
292
437
|
req = double("request")
|
293
|
-
req.
|
294
|
-
@request.setup_credentials
|
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.
|
299
|
-
@request.
|
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.
|
302
|
-
@request.setup_credentials
|
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.
|
308
|
-
|
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.
|
313
|
-
|
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)
|
474
|
+
end
|
475
|
+
|
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)
|
314
479
|
end
|
315
480
|
|
316
|
-
it "catches
|
317
|
-
|
318
|
-
|
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)
|
319
485
|
end
|
320
486
|
|
321
|
-
it "catches
|
322
|
-
|
323
|
-
|
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)
|
324
491
|
end
|
325
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.
|
329
|
-
req.
|
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 =
|
336
|
-
|
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 =
|
341
|
-
|
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 =
|
346
|
-
|
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 =
|
353
|
-
@request.process_result
|
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.
|
360
|
-
|
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
|
-
@
|
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,177 +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].
|
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].
|
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].
|
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].
|
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 =
|
397
|
-
res.
|
398
|
-
@request
|
399
|
-
|
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 =
|
405
|
-
res.
|
406
|
-
@request
|
407
|
-
|
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 =
|
413
|
-
res.
|
414
|
-
@request
|
415
|
-
|
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"]
|
670
|
+
end
|
671
|
+
|
672
|
+
it 'does not log request password' do
|
673
|
+
log = RestClient.log = []
|
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}
|
676
|
+
end
|
677
|
+
|
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
|
416
682
|
end
|
417
683
|
end
|
418
684
|
|
419
685
|
it "strips the charset from the response content type" do
|
420
686
|
log = RestClient.log = []
|
421
|
-
res =
|
422
|
-
res.
|
423
|
-
@request
|
424
|
-
|
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"]
|
425
692
|
end
|
426
693
|
|
427
694
|
describe "timeout" do
|
428
695
|
it "does not set timeouts if not specified" do
|
429
696
|
@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
|
430
|
-
@http.
|
431
|
-
@request.
|
432
|
-
@request.
|
697
|
+
allow(@http).to receive(:request)
|
698
|
+
allow(@request).to receive(:process_result)
|
699
|
+
allow(@request).to receive(:response_log)
|
433
700
|
|
434
|
-
@net.
|
435
|
-
@net.
|
701
|
+
expect(@net).not_to receive(:read_timeout=)
|
702
|
+
expect(@net).not_to receive(:open_timeout=)
|
436
703
|
|
437
|
-
@request.transmit
|
704
|
+
@request.send(:transmit, @uri, 'req', nil)
|
438
705
|
end
|
439
706
|
|
440
|
-
it
|
441
|
-
@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :
|
442
|
-
@http.
|
443
|
-
@request.
|
444
|
-
@request.
|
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)
|
445
712
|
|
446
|
-
@net.
|
713
|
+
expect(@net).to receive(:read_timeout=).with(123)
|
447
714
|
|
448
|
-
@request.transmit
|
715
|
+
@request.send(:transmit, @uri, 'req', nil)
|
449
716
|
end
|
450
717
|
|
451
|
-
it "
|
718
|
+
it "sets open_timeout" do
|
452
719
|
@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :open_timeout => 123)
|
453
|
-
@http.
|
454
|
-
@request.
|
455
|
-
@request.
|
720
|
+
allow(@http).to receive(:request)
|
721
|
+
allow(@request).to receive(:process_result)
|
722
|
+
allow(@request).to receive(:response_log)
|
723
|
+
|
724
|
+
expect(@net).to receive(:open_timeout=).with(123)
|
725
|
+
|
726
|
+
@request.send(:transmit, @uri, 'req', nil)
|
727
|
+
end
|
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)
|
456
734
|
|
457
|
-
@net.
|
735
|
+
expect(@net).to receive(:open_timeout=).with(123)
|
736
|
+
expect(@net).to receive(:read_timeout=).with(123)
|
458
737
|
|
459
|
-
@request.transmit
|
738
|
+
@request.send(:transmit, @uri, 'req', nil)
|
460
739
|
end
|
461
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
|
+
|
462
754
|
it "disable timeout by setting it to nil" do
|
463
|
-
@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :
|
464
|
-
@http.
|
465
|
-
@request.
|
466
|
-
@request.
|
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)
|
759
|
+
|
760
|
+
expect(@net).to receive(:read_timeout=).with(nil)
|
761
|
+
expect(@net).to receive(:open_timeout=).with(nil)
|
762
|
+
|
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)
|
467
771
|
|
468
|
-
@net.
|
469
|
-
@net.should_receive(:open_timeout=).with(nil)
|
772
|
+
expect(@net).to receive(:read_timeout=).with(nil)
|
470
773
|
|
471
|
-
|
774
|
+
expect(fake_stderr {
|
775
|
+
@request.send(:transmit, @uri, 'req', nil)
|
776
|
+
}).to match(/^Deprecated: .*timeout.* nil instead of -1$/)
|
472
777
|
end
|
473
778
|
|
474
779
|
it "deprecated: disable timeout by setting it to -1" do
|
475
|
-
@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :
|
476
|
-
@http.
|
477
|
-
@request.
|
478
|
-
@request.
|
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)
|
479
784
|
|
480
|
-
@request.
|
481
|
-
@net.
|
785
|
+
expect(@request).to receive(:warn)
|
786
|
+
expect(@net).to receive(:read_timeout=).with(nil)
|
482
787
|
|
483
|
-
@request.
|
484
|
-
@net.
|
788
|
+
expect(@request).to receive(:warn)
|
789
|
+
expect(@net).to receive(:open_timeout=).with(nil)
|
485
790
|
|
486
|
-
@request.transmit
|
791
|
+
@request.send(:transmit, @uri, 'req', nil)
|
487
792
|
end
|
488
793
|
end
|
489
794
|
|
490
795
|
describe "ssl" do
|
491
796
|
it "uses SSL when the URI refers to a https address" do
|
492
|
-
@uri.
|
493
|
-
@net.
|
494
|
-
@http.
|
495
|
-
@request.
|
496
|
-
@request.
|
497
|
-
@request.transmit
|
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')
|
498
803
|
end
|
499
804
|
|
500
805
|
it "should default to verifying ssl certificates" do
|
501
|
-
@request.verify_ssl.
|
806
|
+
expect(@request.verify_ssl).to eq OpenSSL::SSL::VERIFY_PEER
|
502
807
|
end
|
503
808
|
|
504
809
|
it "should have expected values for VERIFY_PEER and VERIFY_NONE" do
|
505
|
-
OpenSSL::SSL::VERIFY_NONE.
|
506
|
-
OpenSSL::SSL::VERIFY_PEER.
|
810
|
+
expect(OpenSSL::SSL::VERIFY_NONE).to eq(0)
|
811
|
+
expect(OpenSSL::SSL::VERIFY_PEER).to eq(1)
|
507
812
|
end
|
508
813
|
|
509
814
|
it "should set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is false" do
|
510
815
|
@request = RestClient::Request.new(:method => :put, :verify_ssl => false, :url => 'http://some/resource', :payload => 'payload')
|
511
|
-
@net.
|
512
|
-
@http.
|
513
|
-
@request.
|
514
|
-
@request.
|
515
|
-
@request.transmit
|
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')
|
516
821
|
end
|
517
822
|
|
518
823
|
it "should not set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is true" do
|
519
824
|
@request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload', :verify_ssl => true)
|
520
|
-
@net.
|
521
|
-
@http.
|
522
|
-
@request.
|
523
|
-
@request.
|
524
|
-
@request.transmit
|
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')
|
525
830
|
end
|
526
831
|
|
527
832
|
it "should set net.verify_mode to OpenSSL::SSL::VERIFY_PEER if verify_ssl is true" do
|
528
833
|
@request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload', :verify_ssl => true)
|
529
|
-
@net.
|
530
|
-
@http.
|
531
|
-
@request.
|
532
|
-
@request.
|
533
|
-
@request.transmit
|
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')
|
534
839
|
end
|
535
840
|
|
536
841
|
it "should set net.verify_mode to OpenSSL::SSL::VERIFY_PEER if verify_ssl is not given" do
|
537
842
|
@request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload')
|
538
|
-
@net.
|
539
|
-
@http.
|
540
|
-
@request.
|
541
|
-
@request.
|
542
|
-
@request.transmit
|
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')
|
543
848
|
end
|
544
849
|
|
545
850
|
it "should set net.verify_mode to the passed value if verify_ssl is an OpenSSL constant" do
|
@@ -548,15 +853,15 @@ describe RestClient::Request do
|
|
548
853
|
:url => 'https://some/resource',
|
549
854
|
:payload => 'payload',
|
550
855
|
:verify_ssl => mode )
|
551
|
-
@net.
|
552
|
-
@http.
|
553
|
-
@request.
|
554
|
-
@request.
|
555
|
-
@request.transmit
|
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')
|
556
861
|
end
|
557
862
|
|
558
863
|
it "should default to not having an ssl_client_cert" do
|
559
|
-
@request.ssl_client_cert.
|
864
|
+
expect(@request.ssl_client_cert).to be(nil)
|
560
865
|
end
|
561
866
|
|
562
867
|
it "should set the ssl_version if provided" do
|
@@ -566,11 +871,11 @@ describe RestClient::Request do
|
|
566
871
|
:payload => 'payload',
|
567
872
|
:ssl_version => "TLSv1"
|
568
873
|
)
|
569
|
-
@net.
|
570
|
-
@http.
|
571
|
-
@request.
|
572
|
-
@request.
|
573
|
-
@request.transmit
|
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')
|
574
879
|
end
|
575
880
|
|
576
881
|
it "should not set the ssl_version if not provided" do
|
@@ -579,11 +884,11 @@ describe RestClient::Request do
|
|
579
884
|
:url => 'https://some/resource',
|
580
885
|
:payload => 'payload'
|
581
886
|
)
|
582
|
-
@net.
|
583
|
-
@http.
|
584
|
-
@request.
|
585
|
-
@request.
|
586
|
-
@request.transmit
|
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')
|
587
892
|
end
|
588
893
|
|
589
894
|
it "should set the ssl_ciphers if provided" do
|
@@ -594,11 +899,11 @@ describe RestClient::Request do
|
|
594
899
|
:payload => 'payload',
|
595
900
|
:ssl_ciphers => ciphers
|
596
901
|
)
|
597
|
-
@net.
|
598
|
-
@http.
|
599
|
-
@request.
|
600
|
-
@request.
|
601
|
-
@request.transmit
|
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')
|
602
907
|
end
|
603
908
|
|
604
909
|
it "should not set the ssl_ciphers if set to nil" do
|
@@ -608,61 +913,11 @@ describe RestClient::Request do
|
|
608
913
|
:payload => 'payload',
|
609
914
|
:ssl_ciphers => nil,
|
610
915
|
)
|
611
|
-
@net.
|
612
|
-
@http.
|
613
|
-
@request.
|
614
|
-
@request.
|
615
|
-
@request.transmit
|
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')
|
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')
|
666
921
|
end
|
667
922
|
|
668
923
|
it "should set the ssl_client_cert if provided" do
|
@@ -672,11 +927,11 @@ describe RestClient::Request do
|
|
672
927
|
:payload => 'payload',
|
673
928
|
:ssl_client_cert => "whatsupdoc!"
|
674
929
|
)
|
675
|
-
@net.
|
676
|
-
@http.
|
677
|
-
@request.
|
678
|
-
@request.
|
679
|
-
@request.transmit
|
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')
|
680
935
|
end
|
681
936
|
|
682
937
|
it "should not set the ssl_client_cert if it is not provided" do
|
@@ -685,15 +940,15 @@ describe RestClient::Request do
|
|
685
940
|
:url => 'https://some/resource',
|
686
941
|
:payload => 'payload'
|
687
942
|
)
|
688
|
-
@net.
|
689
|
-
@http.
|
690
|
-
@request.
|
691
|
-
@request.
|
692
|
-
@request.transmit
|
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')
|
693
948
|
end
|
694
949
|
|
695
950
|
it "should default to not having an ssl_client_key" do
|
696
|
-
@request.ssl_client_key.
|
951
|
+
expect(@request.ssl_client_key).to be(nil)
|
697
952
|
end
|
698
953
|
|
699
954
|
it "should set the ssl_client_key if provided" do
|
@@ -703,11 +958,11 @@ describe RestClient::Request do
|
|
703
958
|
:payload => 'payload',
|
704
959
|
:ssl_client_key => "whatsupdoc!"
|
705
960
|
)
|
706
|
-
@net.
|
707
|
-
@http.
|
708
|
-
@request.
|
709
|
-
@request.
|
710
|
-
@request.transmit
|
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')
|
711
966
|
end
|
712
967
|
|
713
968
|
it "should not set the ssl_client_key if it is not provided" do
|
@@ -716,15 +971,15 @@ describe RestClient::Request do
|
|
716
971
|
:url => 'https://some/resource',
|
717
972
|
:payload => 'payload'
|
718
973
|
)
|
719
|
-
@net.
|
720
|
-
@http.
|
721
|
-
@request.
|
722
|
-
@request.
|
723
|
-
@request.transmit
|
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')
|
724
979
|
end
|
725
980
|
|
726
981
|
it "should default to not having an ssl_ca_file" do
|
727
|
-
@request.ssl_ca_file.
|
982
|
+
expect(@request.ssl_ca_file).to be(nil)
|
728
983
|
end
|
729
984
|
|
730
985
|
it "should set the ssl_ca_file if provided" do
|
@@ -734,12 +989,12 @@ describe RestClient::Request do
|
|
734
989
|
:payload => 'payload',
|
735
990
|
:ssl_ca_file => "Certificate Authority File"
|
736
991
|
)
|
737
|
-
@net.
|
738
|
-
@net.
|
739
|
-
@http.
|
740
|
-
@request.
|
741
|
-
@request.
|
742
|
-
@request.transmit
|
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')
|
743
998
|
end
|
744
999
|
|
745
1000
|
it "should not set the ssl_ca_file if it is not provided" do
|
@@ -748,15 +1003,15 @@ describe RestClient::Request do
|
|
748
1003
|
:url => 'https://some/resource',
|
749
1004
|
:payload => 'payload'
|
750
1005
|
)
|
751
|
-
@net.
|
752
|
-
@http.
|
753
|
-
@request.
|
754
|
-
@request.
|
755
|
-
@request.transmit
|
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')
|
756
1011
|
end
|
757
1012
|
|
758
1013
|
it "should default to not having an ssl_ca_path" do
|
759
|
-
@request.ssl_ca_path.
|
1014
|
+
expect(@request.ssl_ca_path).to be(nil)
|
760
1015
|
end
|
761
1016
|
|
762
1017
|
it "should set the ssl_ca_path if provided" do
|
@@ -766,12 +1021,12 @@ describe RestClient::Request do
|
|
766
1021
|
:payload => 'payload',
|
767
1022
|
:ssl_ca_path => "Certificate Authority Path"
|
768
1023
|
)
|
769
|
-
@net.
|
770
|
-
@net.
|
771
|
-
@http.
|
772
|
-
@request.
|
773
|
-
@request.
|
774
|
-
@request.transmit
|
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')
|
775
1030
|
end
|
776
1031
|
|
777
1032
|
it "should not set the ssl_ca_path if it is not provided" do
|
@@ -780,11 +1035,11 @@ describe RestClient::Request do
|
|
780
1035
|
:url => 'https://some/resource',
|
781
1036
|
:payload => 'payload'
|
782
1037
|
)
|
783
|
-
@net.
|
784
|
-
@http.
|
785
|
-
@request.
|
786
|
-
@request.
|
787
|
-
@request.transmit
|
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')
|
788
1043
|
end
|
789
1044
|
|
790
1045
|
it "should set the ssl_cert_store if provided" do
|
@@ -797,13 +1052,13 @@ describe RestClient::Request do
|
|
797
1052
|
:payload => 'payload',
|
798
1053
|
:ssl_cert_store => store
|
799
1054
|
)
|
800
|
-
@net.
|
801
|
-
@net.
|
802
|
-
@net.
|
803
|
-
@http.
|
804
|
-
@request.
|
805
|
-
@request.
|
806
|
-
@request.transmit
|
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')
|
807
1062
|
end
|
808
1063
|
|
809
1064
|
it "should by default set the ssl_cert_store if no CA info is provided" do
|
@@ -812,13 +1067,13 @@ describe RestClient::Request do
|
|
812
1067
|
:url => 'https://some/resource',
|
813
1068
|
:payload => 'payload'
|
814
1069
|
)
|
815
|
-
@net.
|
816
|
-
@net.
|
817
|
-
@net.
|
818
|
-
@http.
|
819
|
-
@request.
|
820
|
-
@request.
|
821
|
-
@request.transmit
|
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')
|
822
1077
|
end
|
823
1078
|
|
824
1079
|
it "should not set the ssl_cert_store if it is set falsy" do
|
@@ -828,11 +1083,11 @@ describe RestClient::Request do
|
|
828
1083
|
:payload => 'payload',
|
829
1084
|
:ssl_cert_store => nil,
|
830
1085
|
)
|
831
|
-
@net.
|
832
|
-
@http.
|
833
|
-
@request.
|
834
|
-
@request.
|
835
|
-
@request.transmit
|
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')
|
836
1091
|
end
|
837
1092
|
|
838
1093
|
it "should not set the ssl_verify_callback by default" do
|
@@ -841,11 +1096,11 @@ describe RestClient::Request do
|
|
841
1096
|
:url => 'https://some/resource',
|
842
1097
|
:payload => 'payload',
|
843
1098
|
)
|
844
|
-
@net.
|
845
|
-
@http.
|
846
|
-
@request.
|
847
|
-
@request.
|
848
|
-
@request.transmit
|
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')
|
849
1104
|
end
|
850
1105
|
|
851
1106
|
it "should set the ssl_verify_callback if passed" do
|
@@ -856,7 +1111,7 @@ describe RestClient::Request do
|
|
856
1111
|
:payload => 'payload',
|
857
1112
|
:ssl_verify_callback => callback,
|
858
1113
|
)
|
859
|
-
@net.
|
1114
|
+
expect(@net).to receive(:verify_callback=).with(callback)
|
860
1115
|
|
861
1116
|
# we'll read cert_store on jruby
|
862
1117
|
# https://github.com/jruby/jruby/issues/597
|
@@ -864,10 +1119,10 @@ describe RestClient::Request do
|
|
864
1119
|
allow(@net).to receive(:cert_store)
|
865
1120
|
end
|
866
1121
|
|
867
|
-
@http.
|
868
|
-
@request.
|
869
|
-
@request.
|
870
|
-
@request.transmit
|
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')
|
871
1126
|
end
|
872
1127
|
|
873
1128
|
# </ssl>
|
@@ -880,11 +1135,11 @@ describe RestClient::Request do
|
|
880
1135
|
:payload => 'payload'
|
881
1136
|
)
|
882
1137
|
net_http_res = Net::HTTPNoContent.new("", "204", "No Content")
|
883
|
-
net_http_res.
|
884
|
-
@http.
|
885
|
-
response = @request.transmit
|
886
|
-
response.
|
887
|
-
response.code.
|
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
|
888
1143
|
end
|
889
1144
|
|
890
1145
|
describe "raw response" do
|
@@ -892,14 +1147,92 @@ describe RestClient::Request do
|
|
892
1147
|
@request = RestClient::Request.new(:method => "get", :url => "example.com", :raw_response => true)
|
893
1148
|
|
894
1149
|
tempfile = double("tempfile")
|
895
|
-
tempfile.
|
896
|
-
tempfile.
|
897
|
-
tempfile.
|
898
|
-
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)
|
899
1154
|
|
900
1155
|
net_http_res = Net::HTTPOK.new(nil, "200", "body")
|
901
|
-
net_http_res.
|
902
|
-
@request.
|
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'
|
903
1236
|
end
|
904
1237
|
end
|
905
1238
|
end
|