rest-client 1.8.0 → 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 +5 -5
- 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 +181 -0
- data/lib/restclient/abstract_response.rb +172 -55
- 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 +19 -0
- data/lib/restclient/raw_response.rb +21 -7
- data/lib/restclient/request.rb +540 -281
- data/lib/restclient/resource.rb +19 -9
- data/lib/restclient/response.rb +75 -6
- data/lib/restclient/utils.rb +274 -0
- data/lib/restclient/version.rb +2 -1
- data/lib/restclient.rb +21 -3
- data/rest-client.gemspec +12 -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 +25 -2
- data/spec/spec_helper.rb +28 -1
- data/spec/unit/_lib.rb +1 -0
- data/spec/unit/abstract_response_spec.rb +95 -38
- 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 -6
- data/spec/unit/request2_spec.rb +34 -12
- data/spec/unit/request_spec.rb +745 -424
- data/spec/unit/resource_spec.rb +31 -27
- data/spec/unit/response_spec.rb +134 -57
- 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 +79 -29
- 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
|
-
|
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
|
-
|
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)
|
314
474
|
end
|
315
475
|
|
316
|
-
it "catches
|
317
|
-
@http.
|
318
|
-
|
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
|
322
|
-
|
323
|
-
|
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.
|
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,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].
|
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"]
|
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'
|
421
|
-
log[0].
|
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
|
425
|
-
|
426
|
-
|
427
|
-
|
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 =
|
434
|
-
res.
|
435
|
-
@request
|
436
|
-
|
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.
|
443
|
-
@request.
|
444
|
-
@request.
|
697
|
+
allow(@http).to receive(:request)
|
698
|
+
allow(@request).to receive(:process_result)
|
699
|
+
allow(@request).to receive(:response_log)
|
445
700
|
|
446
|
-
@net.
|
447
|
-
@net.
|
701
|
+
expect(@net).not_to receive(:read_timeout=)
|
702
|
+
expect(@net).not_to receive(:open_timeout=)
|
448
703
|
|
449
|
-
@request.transmit
|
704
|
+
@request.send(:transmit, @uri, 'req', nil)
|
450
705
|
end
|
451
706
|
|
452
|
-
it
|
453
|
-
@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :
|
454
|
-
@http.
|
455
|
-
@request.
|
456
|
-
@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)
|
457
712
|
|
458
|
-
@net.
|
713
|
+
expect(@net).to receive(:read_timeout=).with(123)
|
459
714
|
|
460
|
-
@request.transmit
|
715
|
+
@request.send(:transmit, @uri, 'req', nil)
|
461
716
|
end
|
462
717
|
|
463
|
-
it "
|
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.
|
466
|
-
@request.
|
467
|
-
@request.
|
720
|
+
allow(@http).to receive(:request)
|
721
|
+
allow(@request).to receive(:process_result)
|
722
|
+
allow(@request).to receive(:response_log)
|
468
723
|
|
469
|
-
@net.
|
724
|
+
expect(@net).to receive(:open_timeout=).with(123)
|
470
725
|
|
471
|
-
@request.transmit
|
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', :
|
476
|
-
@http.
|
477
|
-
@request.
|
478
|
-
@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)
|
479
759
|
|
480
|
-
@net.
|
481
|
-
@net.
|
760
|
+
expect(@net).to receive(:read_timeout=).with(nil)
|
761
|
+
expect(@net).to receive(:open_timeout=).with(nil)
|
482
762
|
|
483
|
-
@request.transmit
|
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', :
|
488
|
-
@http.
|
489
|
-
@request.
|
490
|
-
@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)
|
491
784
|
|
492
|
-
@request.
|
493
|
-
@net.
|
785
|
+
expect(@request).to receive(:warn)
|
786
|
+
expect(@net).to receive(:read_timeout=).with(nil)
|
494
787
|
|
495
|
-
@request.
|
496
|
-
@net.
|
788
|
+
expect(@request).to receive(:warn)
|
789
|
+
expect(@net).to receive(:open_timeout=).with(nil)
|
497
790
|
|
498
|
-
@request.transmit
|
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.
|
505
|
-
@net.
|
506
|
-
@http.
|
507
|
-
@request.
|
508
|
-
@request.
|
509
|
-
@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')
|
510
803
|
end
|
511
804
|
|
512
805
|
it "should default to verifying ssl certificates" do
|
513
|
-
@request.verify_ssl.
|
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.
|
518
|
-
OpenSSL::SSL::VERIFY_PEER.
|
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.
|
524
|
-
@http.
|
525
|
-
@request.
|
526
|
-
@request.
|
527
|
-
@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')
|
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.
|
533
|
-
@http.
|
534
|
-
@request.
|
535
|
-
@request.
|
536
|
-
@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')
|
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.
|
542
|
-
@http.
|
543
|
-
@request.
|
544
|
-
@request.
|
545
|
-
@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')
|
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.
|
551
|
-
@http.
|
552
|
-
@request.
|
553
|
-
@request.
|
554
|
-
@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')
|
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.
|
564
|
-
@http.
|
565
|
-
@request.
|
566
|
-
@request.
|
567
|
-
@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')
|
568
861
|
end
|
569
862
|
|
570
863
|
it "should default to not having an ssl_client_cert" do
|
571
|
-
@request.ssl_client_cert.
|
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.
|
582
|
-
@http.
|
583
|
-
@request.
|
584
|
-
@request.
|
585
|
-
@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')
|
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.
|
595
|
-
@http.
|
596
|
-
@request.
|
597
|
-
@request.
|
598
|
-
@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')
|
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.
|
610
|
-
@http.
|
611
|
-
@request.
|
612
|
-
@request.
|
613
|
-
@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')
|
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.
|
624
|
-
@http.
|
625
|
-
@request.
|
626
|
-
@request.
|
627
|
-
@request.transmit
|
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.
|
688
|
-
@http.
|
689
|
-
@request.
|
690
|
-
@request.
|
691
|
-
@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')
|
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.
|
701
|
-
@http.
|
702
|
-
@request.
|
703
|
-
@request.
|
704
|
-
@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')
|
705
948
|
end
|
706
949
|
|
707
950
|
it "should default to not having an ssl_client_key" do
|
708
|
-
@request.ssl_client_key.
|
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.
|
719
|
-
@http.
|
720
|
-
@request.
|
721
|
-
@request.
|
722
|
-
@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')
|
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.
|
732
|
-
@http.
|
733
|
-
@request.
|
734
|
-
@request.
|
735
|
-
@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')
|
736
979
|
end
|
737
980
|
|
738
981
|
it "should default to not having an ssl_ca_file" do
|
739
|
-
@request.ssl_ca_file.
|
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.
|
750
|
-
@net.
|
751
|
-
@http.
|
752
|
-
@request.
|
753
|
-
@request.
|
754
|
-
@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')
|
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.
|
764
|
-
@http.
|
765
|
-
@request.
|
766
|
-
@request.
|
767
|
-
@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')
|
768
1011
|
end
|
769
1012
|
|
770
1013
|
it "should default to not having an ssl_ca_path" do
|
771
|
-
@request.ssl_ca_path.
|
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.
|
782
|
-
@net.
|
783
|
-
@http.
|
784
|
-
@request.
|
785
|
-
@request.
|
786
|
-
@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')
|
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.
|
796
|
-
@http.
|
797
|
-
@request.
|
798
|
-
@request.
|
799
|
-
@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')
|
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.
|
813
|
-
@net.
|
814
|
-
@net.
|
815
|
-
@http.
|
816
|
-
@request.
|
817
|
-
@request.
|
818
|
-
@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')
|
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.
|
828
|
-
@net.
|
829
|
-
@net.
|
830
|
-
@http.
|
831
|
-
@request.
|
832
|
-
@request.
|
833
|
-
@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')
|
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.
|
844
|
-
@http.
|
845
|
-
@request.
|
846
|
-
@request.
|
847
|
-
@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')
|
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.
|
857
|
-
@http.
|
858
|
-
@request.
|
859
|
-
@request.
|
860
|
-
@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')
|
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.
|
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.
|
880
|
-
@request.
|
881
|
-
@request.
|
882
|
-
@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')
|
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.
|
896
|
-
@http.
|
897
|
-
response = @request.transmit
|
898
|
-
response.
|
899
|
-
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
|
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.
|
908
|
-
tempfile.
|
909
|
-
tempfile.
|
910
|
-
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.
|
914
|
-
@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'
|
915
1236
|
end
|
916
1237
|
end
|
917
1238
|
end
|