rest-client 2.0.0.rc2-x64-mingw32 → 2.0.0.rc3-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop-disables.yml +17 -8
- data/.travis.yml +32 -2
- data/AUTHORS +6 -0
- data/README.md +578 -0
- data/Rakefile +1 -1
- data/history.md +45 -13
- data/lib/restclient.rb +4 -2
- data/lib/restclient/abstract_response.rb +51 -25
- data/lib/restclient/exceptions.rb +45 -6
- data/lib/restclient/params_array.rb +72 -0
- data/lib/restclient/payload.rb +40 -69
- data/lib/restclient/raw_response.rb +1 -2
- data/lib/restclient/request.rb +372 -199
- data/lib/restclient/response.rb +11 -8
- data/lib/restclient/utils.rb +144 -2
- data/lib/restclient/version.rb +1 -1
- data/rest-client.gemspec +5 -5
- data/spec/helpers.rb +8 -0
- data/spec/integration/httpbin_spec.rb +7 -7
- data/spec/integration/integration_spec.rb +34 -24
- data/spec/integration/request_spec.rb +1 -1
- data/spec/spec_helper.rb +8 -1
- data/spec/unit/abstract_response_spec.rb +76 -33
- data/spec/unit/exceptions_spec.rb +27 -21
- data/spec/unit/params_array_spec.rb +36 -0
- data/spec/unit/payload_spec.rb +71 -53
- data/spec/unit/raw_response_spec.rb +3 -3
- data/spec/unit/request2_spec.rb +29 -7
- data/spec/unit/request_spec.rb +552 -415
- data/spec/unit/resource_spec.rb +25 -25
- data/spec/unit/response_spec.rb +86 -64
- data/spec/unit/restclient_spec.rb +13 -13
- data/spec/unit/utils_spec.rb +117 -41
- data/spec/unit/windows/root_certs_spec.rb +2 -2
- metadata +15 -12
- data/README.rdoc +0 -410
@@ -1,6 +1,6 @@
|
|
1
1
|
require_relative '_lib'
|
2
2
|
|
3
|
-
describe RestClient::AbstractResponse do
|
3
|
+
describe RestClient::AbstractResponse, :include_helpers do
|
4
4
|
|
5
5
|
class MyAbstractResponse
|
6
6
|
|
@@ -8,9 +8,8 @@ describe RestClient::AbstractResponse do
|
|
8
8
|
|
9
9
|
attr_accessor :size
|
10
10
|
|
11
|
-
def initialize net_http_res,
|
11
|
+
def initialize net_http_res, request
|
12
12
|
@net_http_res = net_http_res
|
13
|
-
@args = args
|
14
13
|
@request = request
|
15
14
|
end
|
16
15
|
|
@@ -18,85 +17,129 @@ describe RestClient::AbstractResponse do
|
|
18
17
|
|
19
18
|
before do
|
20
19
|
@net_http_res = double('net http response')
|
21
|
-
@request =
|
22
|
-
@response = MyAbstractResponse.new(@net_http_res,
|
20
|
+
@request = request_double(url: 'http://example.com', method: 'get')
|
21
|
+
@response = MyAbstractResponse.new(@net_http_res, @request)
|
23
22
|
end
|
24
23
|
|
25
24
|
it "fetches the numeric response code" do
|
26
|
-
@net_http_res.
|
27
|
-
@response.code.
|
25
|
+
expect(@net_http_res).to receive(:code).and_return('200')
|
26
|
+
expect(@response.code).to eq 200
|
28
27
|
end
|
29
28
|
|
30
29
|
it "has a nice description" do
|
31
|
-
@net_http_res.
|
32
|
-
@net_http_res.
|
33
|
-
@response.description.
|
30
|
+
expect(@net_http_res).to receive(:to_hash).and_return({'Content-Type' => ['application/pdf']})
|
31
|
+
expect(@net_http_res).to receive(:code).and_return('200')
|
32
|
+
expect(@response.description).to eq "200 OK | application/pdf bytes\n"
|
34
33
|
end
|
35
34
|
|
36
35
|
describe '.beautify_headers' do
|
37
36
|
it "beautifies the headers by turning the keys to symbols" do
|
38
37
|
h = RestClient::AbstractResponse.beautify_headers('content-type' => [ 'x' ])
|
39
|
-
h.keys.first.
|
38
|
+
expect(h.keys.first).to eq :content_type
|
40
39
|
end
|
41
40
|
|
42
41
|
it "beautifies the headers by turning the values to strings instead of one-element arrays" do
|
43
42
|
h = RestClient::AbstractResponse.beautify_headers('x' => [ 'text/html' ] )
|
44
|
-
h.values.first.
|
43
|
+
expect(h.values.first).to eq 'text/html'
|
45
44
|
end
|
46
45
|
|
47
46
|
it 'joins multiple header values by comma' do
|
48
|
-
RestClient::AbstractResponse.beautify_headers(
|
47
|
+
expect(RestClient::AbstractResponse.beautify_headers(
|
49
48
|
{'My-Header' => ['one', 'two']}
|
50
|
-
).
|
49
|
+
)).to eq({:my_header => 'one, two'})
|
51
50
|
end
|
52
51
|
|
53
52
|
it 'leaves set-cookie headers as array' do
|
54
|
-
RestClient::AbstractResponse.beautify_headers(
|
53
|
+
expect(RestClient::AbstractResponse.beautify_headers(
|
55
54
|
{'Set-Cookie' => ['cookie1=foo', 'cookie2=bar']}
|
56
|
-
).
|
55
|
+
)).to eq({:set_cookie => ['cookie1=foo', 'cookie2=bar']})
|
57
56
|
end
|
58
57
|
end
|
59
58
|
|
60
59
|
it "fetches the headers" do
|
61
|
-
@net_http_res.
|
62
|
-
@response.headers.
|
60
|
+
expect(@net_http_res).to receive(:to_hash).and_return('content-type' => [ 'text/html' ])
|
61
|
+
expect(@response.headers).to eq({ :content_type => 'text/html' })
|
63
62
|
end
|
64
63
|
|
65
64
|
it "extracts cookies from response headers" do
|
66
|
-
@net_http_res.
|
67
|
-
@response.cookies.
|
65
|
+
expect(@net_http_res).to receive(:to_hash).and_return('set-cookie' => ['session_id=1; path=/'])
|
66
|
+
expect(@response.cookies).to eq({ 'session_id' => '1' })
|
68
67
|
end
|
69
68
|
|
70
69
|
it "extract strange cookies" do
|
71
|
-
@net_http_res.
|
72
|
-
@response.headers.
|
73
|
-
@response.cookies.
|
70
|
+
expect(@net_http_res).to receive(:to_hash).and_return('set-cookie' => ['session_id=ZJ/HQVH6YE+rVkTpn0zvTQ==; path=/'])
|
71
|
+
expect(@response.headers).to eq({:set_cookie => ['session_id=ZJ/HQVH6YE+rVkTpn0zvTQ==; path=/']})
|
72
|
+
expect(@response.cookies).to eq({ 'session_id' => 'ZJ/HQVH6YE+rVkTpn0zvTQ==' })
|
74
73
|
end
|
75
74
|
|
76
75
|
it "doesn't escape cookies" do
|
77
|
-
@net_http_res.
|
78
|
-
@response.cookies.
|
76
|
+
expect(@net_http_res).to receive(:to_hash).and_return('set-cookie' => ['session_id=BAh7BzoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOgpsb2dpbiIKYWRtaW4%3D%0A--08114ba654f17c04d20dcc5228ec672508f738ca; path=/'])
|
77
|
+
expect(@response.cookies).to eq({ 'session_id' => 'BAh7BzoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOgpsb2dpbiIKYWRtaW4%3D%0A--08114ba654f17c04d20dcc5228ec672508f738ca' })
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '.cookie_jar' do
|
81
|
+
it 'extracts cookies into cookie jar' do
|
82
|
+
expect(@net_http_res).to receive(:to_hash).and_return('set-cookie' => ['session_id=1; path=/'])
|
83
|
+
expect(@response.cookie_jar).to be_a HTTP::CookieJar
|
84
|
+
|
85
|
+
cookie = @response.cookie_jar.cookies.first
|
86
|
+
expect(cookie.domain).to eq 'example.com'
|
87
|
+
expect(cookie.name).to eq 'session_id'
|
88
|
+
expect(cookie.value).to eq '1'
|
89
|
+
expect(cookie.path).to eq '/'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'handles cookies when URI scheme is implicit' do
|
93
|
+
net_http_res = double('net http response')
|
94
|
+
expect(net_http_res).to receive(:to_hash).and_return('set-cookie' => ['session_id=1; path=/'])
|
95
|
+
request = double(url: 'example.com', uri: URI.parse('http://example.com'),
|
96
|
+
method: 'get', cookie_jar: HTTP::CookieJar.new)
|
97
|
+
response = MyAbstractResponse.new(net_http_res, request)
|
98
|
+
expect(response.cookie_jar).to be_a HTTP::CookieJar
|
99
|
+
|
100
|
+
cookie = response.cookie_jar.cookies.first
|
101
|
+
expect(cookie.domain).to eq 'example.com'
|
102
|
+
expect(cookie.name).to eq 'session_id'
|
103
|
+
expect(cookie.value).to eq '1'
|
104
|
+
expect(cookie.path).to eq '/'
|
105
|
+
end
|
79
106
|
end
|
80
107
|
|
81
108
|
it "can access the net http result directly" do
|
82
|
-
@response.net_http_res.
|
109
|
+
expect(@response.net_http_res).to eq @net_http_res
|
83
110
|
end
|
84
111
|
|
85
112
|
describe "#return!" do
|
86
113
|
it "should return the response itself on 200-codes" do
|
87
|
-
@net_http_res.
|
88
|
-
@response.return
|
114
|
+
expect(@net_http_res).to receive(:code).and_return('200')
|
115
|
+
expect(@response.return!).to be_equal(@response)
|
89
116
|
end
|
90
117
|
|
91
118
|
it "should raise RequestFailed on unknown codes" do
|
92
|
-
@net_http_res.
|
93
|
-
|
119
|
+
expect(@net_http_res).to receive(:code).and_return('1000')
|
120
|
+
expect { @response.return! }.to raise_error RestClient::RequestFailed
|
94
121
|
end
|
95
122
|
|
96
123
|
it "should raise an error on a redirection after non-GET/HEAD requests" do
|
97
|
-
@net_http_res.
|
98
|
-
@
|
99
|
-
|
124
|
+
expect(@net_http_res).to receive(:code).and_return('301')
|
125
|
+
expect(@request).to receive(:method).and_return('put')
|
126
|
+
expect(@response).not_to receive(:follow_redirection)
|
127
|
+
expect { @response.return! }.to raise_error RestClient::RequestFailed
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should follow 302 redirect" do
|
131
|
+
expect(@net_http_res).to receive(:code).and_return('302')
|
132
|
+
expect(@response).to receive(:check_max_redirects).and_return('fake-check')
|
133
|
+
expect(@response).to receive(:follow_redirection).and_return('fake-redirection')
|
134
|
+
expect(@response.return!).to eq 'fake-redirection'
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should gracefully handle 302 redirect with no location header" do
|
138
|
+
@net_http_res = response_double(code: 302, location: nil)
|
139
|
+
@request = request_double()
|
140
|
+
@response = MyAbstractResponse.new(@net_http_res, @request)
|
141
|
+
expect(@response).to receive(:check_max_redirects).and_return('fake-check')
|
142
|
+
expect { @response.return! }.to raise_error RestClient::Found
|
100
143
|
end
|
101
144
|
end
|
102
145
|
end
|
@@ -3,30 +3,30 @@ require_relative '_lib'
|
|
3
3
|
describe RestClient::Exception do
|
4
4
|
it "returns a 'message' equal to the class name if the message is not set, because 'message' should not be nil" do
|
5
5
|
e = RestClient::Exception.new
|
6
|
-
e.message.
|
6
|
+
expect(e.message).to eq "RestClient::Exception"
|
7
7
|
end
|
8
8
|
|
9
9
|
it "returns the 'message' that was set" do
|
10
10
|
e = RestClient::Exception.new
|
11
11
|
message = "An explicitly set message"
|
12
12
|
e.message = message
|
13
|
-
e.message.
|
13
|
+
expect(e.message).to eq message
|
14
14
|
end
|
15
15
|
|
16
16
|
it "sets the exception message to ErrorMessage" do
|
17
|
-
RestClient::ResourceNotFound.new.message.
|
17
|
+
expect(RestClient::ResourceNotFound.new.message).to eq 'Not Found'
|
18
18
|
end
|
19
19
|
|
20
20
|
it "contains exceptions in RestClient" do
|
21
|
-
RestClient::Unauthorized.new.
|
22
|
-
RestClient::ServerBrokeConnection.new.
|
21
|
+
expect(RestClient::Unauthorized.new).to be_a_kind_of(RestClient::Exception)
|
22
|
+
expect(RestClient::ServerBrokeConnection.new).to be_a_kind_of(RestClient::Exception)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
describe RestClient::ServerBrokeConnection do
|
27
27
|
it "should have a default message of 'Server broke connection'" do
|
28
28
|
e = RestClient::ServerBrokeConnection.new
|
29
|
-
e.message.
|
29
|
+
expect(e.message).to eq 'Server broke connection'
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -40,21 +40,21 @@ describe RestClient::RequestFailed do
|
|
40
40
|
begin
|
41
41
|
raise RestClient::RequestFailed, response
|
42
42
|
rescue RestClient::RequestFailed => e
|
43
|
-
e.response.
|
43
|
+
expect(e.response).to eq response
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
it "http_code convenience method for fetching the code as an integer" do
|
48
|
-
RestClient::RequestFailed.new(@response).http_code.
|
48
|
+
expect(RestClient::RequestFailed.new(@response).http_code).to eq 502
|
49
49
|
end
|
50
50
|
|
51
51
|
it "http_body convenience method for fetching the body (decoding when necessary)" do
|
52
|
-
RestClient::RequestFailed.new(@response).http_code.
|
53
|
-
RestClient::RequestFailed.new(@response).message.
|
52
|
+
expect(RestClient::RequestFailed.new(@response).http_code).to eq 502
|
53
|
+
expect(RestClient::RequestFailed.new(@response).message).to eq 'HTTP status code 502'
|
54
54
|
end
|
55
55
|
|
56
56
|
it "shows the status code in the message" do
|
57
|
-
RestClient::RequestFailed.new(@response).to_s.
|
57
|
+
expect(RestClient::RequestFailed.new(@response).to_s).to match(/502/)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -64,7 +64,7 @@ describe RestClient::ResourceNotFound do
|
|
64
64
|
begin
|
65
65
|
raise RestClient::ResourceNotFound, response
|
66
66
|
rescue RestClient::ResourceNotFound => e
|
67
|
-
e.response.
|
67
|
+
expect(e.response).to eq response
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -75,28 +75,34 @@ describe RestClient::ResourceNotFound do
|
|
75
75
|
RestClient.get "www.example.com"
|
76
76
|
raise
|
77
77
|
rescue RestClient::ResourceNotFound => e
|
78
|
-
e.response.body.
|
78
|
+
expect(e.response.body).to eq body
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
83
|
describe "backwards compatibility" do
|
84
84
|
it 'aliases RestClient::NotFound as ResourceNotFound' do
|
85
|
-
RestClient::ResourceNotFound.
|
85
|
+
expect(RestClient::ResourceNotFound).to eq RestClient::NotFound
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'aliases old names for HTTP 413, 414, 416' do
|
89
|
+
expect(RestClient::RequestEntityTooLarge).to eq RestClient::PayloadTooLarge
|
90
|
+
expect(RestClient::RequestURITooLong).to eq RestClient::URITooLong
|
91
|
+
expect(RestClient::RequestedRangeNotSatisfiable).to eq RestClient::RangeNotSatisfiable
|
86
92
|
end
|
87
93
|
|
88
94
|
it 'subclasses NotFound from RequestFailed, ExceptionWithResponse' do
|
89
|
-
RestClient::NotFound.
|
90
|
-
RestClient::NotFound.
|
95
|
+
expect(RestClient::NotFound).to be < RestClient::RequestFailed
|
96
|
+
expect(RestClient::NotFound).to be < RestClient::ExceptionWithResponse
|
91
97
|
end
|
92
98
|
|
93
99
|
it 'subclasses timeout from RestClient::RequestTimeout, RequestFailed, EWR' do
|
94
|
-
RestClient::Exceptions::OpenTimeout.
|
95
|
-
RestClient::Exceptions::ReadTimeout.
|
100
|
+
expect(RestClient::Exceptions::OpenTimeout).to be < RestClient::Exceptions::Timeout
|
101
|
+
expect(RestClient::Exceptions::ReadTimeout).to be < RestClient::Exceptions::Timeout
|
96
102
|
|
97
|
-
RestClient::Exceptions::Timeout.
|
98
|
-
RestClient::Exceptions::Timeout.
|
99
|
-
RestClient::Exceptions::Timeout.
|
103
|
+
expect(RestClient::Exceptions::Timeout).to be < RestClient::RequestTimeout
|
104
|
+
expect(RestClient::Exceptions::Timeout).to be < RestClient::RequestFailed
|
105
|
+
expect(RestClient::Exceptions::Timeout).to be < RestClient::ExceptionWithResponse
|
100
106
|
end
|
101
107
|
|
102
108
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative '_lib'
|
2
|
+
|
3
|
+
describe RestClient::ParamsArray do
|
4
|
+
|
5
|
+
describe '.new' do
|
6
|
+
it 'accepts various types of containers' do
|
7
|
+
as_array = [[:foo, 123], [:foo, 456], [:bar, 789], [:empty, nil]]
|
8
|
+
[
|
9
|
+
[[:foo, 123], [:foo, 456], [:bar, 789], [:empty, nil]],
|
10
|
+
[{foo: 123}, {foo: 456}, {bar: 789}, {empty: nil}],
|
11
|
+
[{foo: 123}, {foo: 456}, {bar: 789}, {empty: nil}],
|
12
|
+
[{foo: 123}, [:foo, 456], {bar: 789}, {empty: nil}],
|
13
|
+
[{foo: 123}, [:foo, 456], {bar: 789}, [:empty]],
|
14
|
+
].each do |input|
|
15
|
+
expect(RestClient::ParamsArray.new(input).to_a).to eq as_array
|
16
|
+
end
|
17
|
+
|
18
|
+
expect(RestClient::ParamsArray.new([]).to_a).to eq []
|
19
|
+
expect(RestClient::ParamsArray.new([]).empty?).to eq true
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'rejects various invalid input' do
|
23
|
+
expect {
|
24
|
+
RestClient::ParamsArray.new([[]])
|
25
|
+
}.to raise_error(IndexError)
|
26
|
+
|
27
|
+
expect {
|
28
|
+
RestClient::ParamsArray.new([[1,2,3]])
|
29
|
+
}.to raise_error(ArgumentError)
|
30
|
+
|
31
|
+
expect {
|
32
|
+
RestClient::ParamsArray.new([1,2,3])
|
33
|
+
}.to raise_error(NoMethodError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/unit/payload_spec.rb
CHANGED
@@ -3,58 +3,66 @@
|
|
3
3
|
require_relative '_lib'
|
4
4
|
|
5
5
|
describe RestClient::Payload do
|
6
|
+
context "Base Payload" do
|
7
|
+
it "should reset stream after to_s" do
|
8
|
+
payload = RestClient::Payload::Base.new('foobar')
|
9
|
+
expect(payload.to_s).to eq 'foobar'
|
10
|
+
expect(payload.to_s).to eq 'foobar'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
6
14
|
context "A regular Payload" do
|
7
15
|
it "should use standard enctype as default content-type" do
|
8
|
-
RestClient::Payload::UrlEncoded.new({}).headers['Content-Type'].
|
9
|
-
|
16
|
+
expect(RestClient::Payload::UrlEncoded.new({}).headers['Content-Type']).
|
17
|
+
to eq 'application/x-www-form-urlencoded'
|
10
18
|
end
|
11
19
|
|
12
20
|
it "should form properly encoded params" do
|
13
|
-
RestClient::Payload::UrlEncoded.new({:foo => 'bar'}).to_s.
|
14
|
-
|
15
|
-
["foo=bar&baz=qux", "baz=qux&foo=bar"].
|
21
|
+
expect(RestClient::Payload::UrlEncoded.new({:foo => 'bar'}).to_s).
|
22
|
+
to eq "foo=bar"
|
23
|
+
expect(["foo=bar&baz=qux", "baz=qux&foo=bar"]).to include(
|
16
24
|
RestClient::Payload::UrlEncoded.new({:foo => 'bar', :baz => 'qux'}).to_s)
|
17
25
|
end
|
18
26
|
|
19
27
|
it "should escape parameters" do
|
20
|
-
RestClient::Payload::UrlEncoded.new({'foo ' => '
|
21
|
-
|
28
|
+
expect(RestClient::Payload::UrlEncoded.new({'foo + bar' => 'baz'}).to_s).
|
29
|
+
to eq "foo+%2B+bar=baz"
|
22
30
|
end
|
23
31
|
|
24
32
|
it "should properly handle hashes as parameter" do
|
25
|
-
RestClient::Payload::UrlEncoded.new({:foo => {:bar => 'baz'}}).to_s.
|
26
|
-
|
27
|
-
RestClient::Payload::UrlEncoded.new({:foo => {:bar => {:baz => 'qux'}}}).to_s.
|
28
|
-
|
33
|
+
expect(RestClient::Payload::UrlEncoded.new({:foo => {:bar => 'baz'}}).to_s).
|
34
|
+
to eq "foo[bar]=baz"
|
35
|
+
expect(RestClient::Payload::UrlEncoded.new({:foo => {:bar => {:baz => 'qux'}}}).to_s).
|
36
|
+
to eq "foo[bar][baz]=qux"
|
29
37
|
end
|
30
38
|
|
31
39
|
it "should handle many attributes inside a hash" do
|
32
40
|
parameters = RestClient::Payload::UrlEncoded.new({:foo => {:bar => 'baz', :baz => 'qux'}}).to_s
|
33
|
-
parameters.
|
41
|
+
expect(parameters).to eq 'foo[bar]=baz&foo[baz]=qux'
|
34
42
|
end
|
35
43
|
|
36
|
-
it "should handle attributes inside
|
44
|
+
it "should handle attributes inside an array inside an hash" do
|
37
45
|
parameters = RestClient::Payload::UrlEncoded.new({"foo" => [{"bar" => 'baz'}, {"bar" => 'qux'}]}).to_s
|
38
|
-
parameters.
|
46
|
+
expect(parameters).to eq 'foo[][bar]=baz&foo[][bar]=qux'
|
39
47
|
end
|
40
48
|
|
41
|
-
it "should handle
|
42
|
-
parameters = RestClient::Payload::UrlEncoded.new({"foo" =>
|
43
|
-
parameters.
|
49
|
+
it "should handle arrays inside a hash inside a hash" do
|
50
|
+
parameters = RestClient::Payload::UrlEncoded.new({"foo" => {'even' => [0, 2], 'odd' => [1, 3]}}).to_s
|
51
|
+
expect(parameters).to eq 'foo[even][]=0&foo[even][]=2&foo[odd][]=1&foo[odd][]=3'
|
44
52
|
end
|
45
53
|
|
46
54
|
it "should form properly use symbols as parameters" do
|
47
|
-
RestClient::Payload::UrlEncoded.new({:foo => :bar}).to_s.
|
48
|
-
|
49
|
-
RestClient::Payload::UrlEncoded.new({:foo => {:bar => :baz}}).to_s.
|
50
|
-
|
55
|
+
expect(RestClient::Payload::UrlEncoded.new({:foo => :bar}).to_s).
|
56
|
+
to eq "foo=bar"
|
57
|
+
expect(RestClient::Payload::UrlEncoded.new({:foo => {:bar => :baz}}).to_s).
|
58
|
+
to eq "foo[bar]=baz"
|
51
59
|
end
|
52
60
|
|
53
61
|
it "should properly handle arrays as repeated parameters" do
|
54
|
-
RestClient::Payload::UrlEncoded.new({:foo => ['bar']}).to_s.
|
55
|
-
|
56
|
-
RestClient::Payload::UrlEncoded.new({:foo => ['bar', 'baz']}).to_s.
|
57
|
-
|
62
|
+
expect(RestClient::Payload::UrlEncoded.new({:foo => ['bar']}).to_s).
|
63
|
+
to eq "foo[]=bar"
|
64
|
+
expect(RestClient::Payload::UrlEncoded.new({:foo => ['bar', 'baz']}).to_s).
|
65
|
+
to eq "foo[]=bar&foo[]=baz"
|
58
66
|
end
|
59
67
|
|
60
68
|
it 'should not close if stream already closed' do
|
@@ -67,8 +75,8 @@ describe RestClient::Payload do
|
|
67
75
|
context "A multipart Payload" do
|
68
76
|
it "should use standard enctype as default content-type" do
|
69
77
|
m = RestClient::Payload::Multipart.new({})
|
70
|
-
m.
|
71
|
-
m.headers['Content-Type'].
|
78
|
+
allow(m).to receive(:boundary).and_return(123)
|
79
|
+
expect(m.headers['Content-Type']).to eq 'multipart/form-data; boundary=123'
|
72
80
|
end
|
73
81
|
|
74
82
|
it 'should not error on close if stream already closed' do
|
@@ -78,7 +86,7 @@ describe RestClient::Payload do
|
|
78
86
|
|
79
87
|
it "should form properly separated multipart data" do
|
80
88
|
m = RestClient::Payload::Multipart.new([[:bar, "baz"], [:foo, "bar"]])
|
81
|
-
m.to_s.
|
89
|
+
expect(m.to_s).to eq <<-EOS
|
82
90
|
--#{m.boundary}\r
|
83
91
|
Content-Disposition: form-data; name="bar"\r
|
84
92
|
\r
|
@@ -93,7 +101,7 @@ bar\r
|
|
93
101
|
|
94
102
|
it "should not escape parameters names" do
|
95
103
|
m = RestClient::Payload::Multipart.new([["bar ", "baz"]])
|
96
|
-
m.to_s.
|
104
|
+
expect(m.to_s).to eq <<-EOS
|
97
105
|
--#{m.boundary}\r
|
98
106
|
Content-Disposition: form-data; name="bar "\r
|
99
107
|
\r
|
@@ -105,7 +113,7 @@ baz\r
|
|
105
113
|
it "should form properly separated multipart data" do
|
106
114
|
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
107
115
|
m = RestClient::Payload::Multipart.new({:foo => f})
|
108
|
-
m.to_s.
|
116
|
+
expect(m.to_s).to eq <<-EOS
|
109
117
|
--#{m.boundary}\r
|
110
118
|
Content-Disposition: form-data; name="foo"; filename="master_shake.jpg"\r
|
111
119
|
Content-Type: image/jpeg\r
|
@@ -118,7 +126,7 @@ Content-Type: image/jpeg\r
|
|
118
126
|
it "should ignore the name attribute when it's not set" do
|
119
127
|
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
120
128
|
m = RestClient::Payload::Multipart.new({nil => f})
|
121
|
-
m.to_s.
|
129
|
+
expect(m.to_s).to eq <<-EOS
|
122
130
|
--#{m.boundary}\r
|
123
131
|
Content-Disposition: form-data; filename="master_shake.jpg"\r
|
124
132
|
Content-Type: image/jpeg\r
|
@@ -133,7 +141,7 @@ Content-Type: image/jpeg\r
|
|
133
141
|
f.instance_eval "def content_type; 'text/plain'; end"
|
134
142
|
f.instance_eval "def original_filename; 'foo.txt'; end"
|
135
143
|
m = RestClient::Payload::Multipart.new({:foo => f})
|
136
|
-
m.to_s.
|
144
|
+
expect(m.to_s).to eq <<-EOS
|
137
145
|
--#{m.boundary}\r
|
138
146
|
Content-Disposition: form-data; name="foo"; filename="foo.txt"\r
|
139
147
|
Content-Type: text/plain\r
|
@@ -145,7 +153,7 @@ Content-Type: text/plain\r
|
|
145
153
|
|
146
154
|
it "should handle hash in hash parameters" do
|
147
155
|
m = RestClient::Payload::Multipart.new({:bar => {:baz => "foo"}})
|
148
|
-
m.to_s.
|
156
|
+
expect(m.to_s).to eq <<-EOS
|
149
157
|
--#{m.boundary}\r
|
150
158
|
Content-Disposition: form-data; name="bar[baz]"\r
|
151
159
|
\r
|
@@ -157,7 +165,7 @@ foo\r
|
|
157
165
|
f.instance_eval "def content_type; 'text/plain'; end"
|
158
166
|
f.instance_eval "def original_filename; 'foo.txt'; end"
|
159
167
|
m = RestClient::Payload::Multipart.new({:foo => {:bar => f}})
|
160
|
-
m.to_s.
|
168
|
+
expect(m.to_s).to eq <<-EOS
|
161
169
|
--#{m.boundary}\r
|
162
170
|
Content-Disposition: form-data; name="foo[bar]"; filename="foo.txt"\r
|
163
171
|
Content-Type: text/plain\r
|
@@ -167,29 +175,36 @@ Content-Type: text/plain\r
|
|
167
175
|
EOS
|
168
176
|
end
|
169
177
|
|
178
|
+
it 'should correctly format hex boundary' do
|
179
|
+
allow(SecureRandom).to receive(:base64).with(12).and_return('TGs89+ttw/xna6TV')
|
180
|
+
f = File.new(File.dirname(__FILE__) + '/master_shake.jpg')
|
181
|
+
m = RestClient::Payload::Multipart.new({:foo => f})
|
182
|
+
expect(m.boundary).to eq('-' * 4 + 'RubyFormBoundary' + 'TGs89AttwBxna6TV')
|
183
|
+
end
|
184
|
+
|
170
185
|
end
|
171
186
|
|
172
187
|
context "streamed payloads" do
|
173
188
|
it "should properly determine the size of file payloads" do
|
174
189
|
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
175
190
|
payload = RestClient::Payload.generate(f)
|
176
|
-
payload.size.
|
177
|
-
payload.length.
|
191
|
+
expect(payload.size).to eq 76_988
|
192
|
+
expect(payload.length).to eq 76_988
|
178
193
|
end
|
179
194
|
|
180
195
|
it "should properly determine the size of other kinds of streaming payloads" do
|
181
196
|
s = StringIO.new 'foo'
|
182
197
|
payload = RestClient::Payload.generate(s)
|
183
|
-
payload.size.
|
184
|
-
payload.length.
|
198
|
+
expect(payload.size).to eq 3
|
199
|
+
expect(payload.length).to eq 3
|
185
200
|
|
186
201
|
begin
|
187
202
|
f = Tempfile.new "rest-client"
|
188
203
|
f.write 'foo bar'
|
189
204
|
|
190
205
|
payload = RestClient::Payload.generate(f)
|
191
|
-
payload.size.
|
192
|
-
payload.length.
|
206
|
+
expect(payload.size).to eq 7
|
207
|
+
expect(payload.length).to eq 7
|
193
208
|
ensure
|
194
209
|
f.close
|
195
210
|
end
|
@@ -198,48 +213,51 @@ Content-Type: text/plain\r
|
|
198
213
|
|
199
214
|
context "Payload generation" do
|
200
215
|
it "should recognize standard urlencoded params" do
|
201
|
-
RestClient::Payload.generate({"foo" => 'bar'}).
|
216
|
+
expect(RestClient::Payload.generate({"foo" => 'bar'})).to be_kind_of(RestClient::Payload::UrlEncoded)
|
202
217
|
end
|
203
218
|
|
204
219
|
it "should recognize multipart params" do
|
205
220
|
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
206
|
-
RestClient::Payload.generate({"foo" => f}).
|
221
|
+
expect(RestClient::Payload.generate({"foo" => f})).to be_kind_of(RestClient::Payload::Multipart)
|
207
222
|
end
|
208
223
|
|
209
224
|
it "should be multipart if forced" do
|
210
|
-
RestClient::Payload.generate({"foo" => "bar", :multipart => true}).
|
225
|
+
expect(RestClient::Payload.generate({"foo" => "bar", :multipart => true})).to be_kind_of(RestClient::Payload::Multipart)
|
211
226
|
end
|
212
227
|
|
228
|
+
it "should handle deeply nested multipart" do
|
229
|
+
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
230
|
+
params = {foo: RestClient::ParamsArray.new({nested: f})}
|
231
|
+
expect(RestClient::Payload.generate(params)).to be_kind_of(RestClient::Payload::Multipart)
|
232
|
+
end
|
233
|
+
|
234
|
+
|
213
235
|
it "should return data if no of the above" do
|
214
|
-
RestClient::Payload.generate("data").
|
236
|
+
expect(RestClient::Payload.generate("data")).to be_kind_of(RestClient::Payload::Base)
|
215
237
|
end
|
216
238
|
|
217
239
|
it "should recognize nested multipart payloads in hashes" do
|
218
240
|
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
219
|
-
RestClient::Payload.generate({"foo" => {"file" => f}}).
|
241
|
+
expect(RestClient::Payload.generate({"foo" => {"file" => f}})).to be_kind_of(RestClient::Payload::Multipart)
|
220
242
|
end
|
221
243
|
|
222
244
|
it "should recognize nested multipart payloads in arrays" do
|
223
245
|
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
224
|
-
RestClient::Payload.generate({"foo" => [f]}).
|
246
|
+
expect(RestClient::Payload.generate({"foo" => [f]})).to be_kind_of(RestClient::Payload::Multipart)
|
225
247
|
end
|
226
248
|
|
227
249
|
it "should recognize file payloads that can be streamed" do
|
228
250
|
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
229
|
-
RestClient::Payload.generate(f).
|
251
|
+
expect(RestClient::Payload.generate(f)).to be_kind_of(RestClient::Payload::Streamed)
|
230
252
|
end
|
231
253
|
|
232
254
|
it "should recognize other payloads that can be streamed" do
|
233
|
-
RestClient::Payload.generate(StringIO.new('foo')).
|
255
|
+
expect(RestClient::Payload.generate(StringIO.new('foo'))).to be_kind_of(RestClient::Payload::Streamed)
|
234
256
|
end
|
235
257
|
|
236
258
|
# hashery gem introduces Hash#read convenience method. Existence of #read method used to determine of content is streameable :/
|
237
259
|
it "shouldn't treat hashes as streameable" do
|
238
|
-
RestClient::Payload.generate({"foo" => 'bar'}).
|
260
|
+
expect(RestClient::Payload.generate({"foo" => 'bar'})).to be_kind_of(RestClient::Payload::UrlEncoded)
|
239
261
|
end
|
240
262
|
end
|
241
|
-
|
242
|
-
class HashMapForTesting < Hash
|
243
|
-
alias :read :[]
|
244
|
-
end
|
245
263
|
end
|