rest-client 2.0.0.rc2-x64-mingw32 → 2.0.0.rc3-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/spec/unit/utils_spec.rb
CHANGED
@@ -4,68 +4,144 @@ describe RestClient::Utils do
|
|
4
4
|
describe '.get_encoding_from_headers' do
|
5
5
|
it 'assumes no encoding by default for text' do
|
6
6
|
headers = {:content_type => 'text/plain'}
|
7
|
-
RestClient::Utils.get_encoding_from_headers(headers).
|
8
|
-
|
7
|
+
expect(RestClient::Utils.get_encoding_from_headers(headers)).
|
8
|
+
to eq nil
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'returns nil on failures' do
|
12
|
-
RestClient::Utils.get_encoding_from_headers(
|
13
|
-
{:content_type => 'blah'}).
|
14
|
-
RestClient::Utils.get_encoding_from_headers(
|
15
|
-
{}).
|
16
|
-
RestClient::Utils.get_encoding_from_headers(
|
17
|
-
{:content_type => 'foo; bar=baz'}).
|
12
|
+
expect(RestClient::Utils.get_encoding_from_headers(
|
13
|
+
{:content_type => 'blah'})).to eq nil
|
14
|
+
expect(RestClient::Utils.get_encoding_from_headers(
|
15
|
+
{})).to eq nil
|
16
|
+
expect(RestClient::Utils.get_encoding_from_headers(
|
17
|
+
{:content_type => 'foo; bar=baz'})).to eq nil
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'handles various charsets' do
|
21
|
-
RestClient::Utils.get_encoding_from_headers(
|
22
|
-
{:content_type => 'text/plain; charset=UTF-8'}).
|
23
|
-
RestClient::Utils.get_encoding_from_headers(
|
24
|
-
{:content_type => 'application/json; charset=ISO-8859-1'}).
|
25
|
-
|
26
|
-
RestClient::Utils.get_encoding_from_headers(
|
27
|
-
{:content_type => 'text/html; charset=windows-1251'}).
|
28
|
-
|
29
|
-
|
30
|
-
RestClient::Utils.get_encoding_from_headers(
|
31
|
-
{:content_type => 'text/html; charset="UTF-16"'}).
|
32
|
-
|
21
|
+
expect(RestClient::Utils.get_encoding_from_headers(
|
22
|
+
{:content_type => 'text/plain; charset=UTF-8'})).to eq 'UTF-8'
|
23
|
+
expect(RestClient::Utils.get_encoding_from_headers(
|
24
|
+
{:content_type => 'application/json; charset=ISO-8859-1'})).
|
25
|
+
to eq 'ISO-8859-1'
|
26
|
+
expect(RestClient::Utils.get_encoding_from_headers(
|
27
|
+
{:content_type => 'text/html; charset=windows-1251'})).
|
28
|
+
to eq 'windows-1251'
|
29
|
+
|
30
|
+
expect(RestClient::Utils.get_encoding_from_headers(
|
31
|
+
{:content_type => 'text/html; charset="UTF-16"'})).
|
32
|
+
to eq 'UTF-16'
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
describe '.cgi_parse_header' do
|
37
37
|
it 'parses headers' do
|
38
|
-
RestClient::Utils.cgi_parse_header('text/plain').
|
39
|
-
|
38
|
+
expect(RestClient::Utils.cgi_parse_header('text/plain')).
|
39
|
+
to eq ['text/plain', {}]
|
40
40
|
|
41
|
-
RestClient::Utils.cgi_parse_header('text/vnd.just.made.this.up ; ').
|
42
|
-
|
41
|
+
expect(RestClient::Utils.cgi_parse_header('text/vnd.just.made.this.up ; ')).
|
42
|
+
to eq ['text/vnd.just.made.this.up', {}]
|
43
43
|
|
44
|
-
RestClient::Utils.cgi_parse_header('text/plain;charset=us-ascii').
|
45
|
-
|
44
|
+
expect(RestClient::Utils.cgi_parse_header('text/plain;charset=us-ascii')).
|
45
|
+
to eq ['text/plain', {'charset' => 'us-ascii'}]
|
46
46
|
|
47
|
-
RestClient::Utils.cgi_parse_header('text/plain ; charset="us-ascii"').
|
48
|
-
|
47
|
+
expect(RestClient::Utils.cgi_parse_header('text/plain ; charset="us-ascii"')).
|
48
|
+
to eq ['text/plain', {'charset' => 'us-ascii'}]
|
49
49
|
|
50
|
-
RestClient::Utils.cgi_parse_header(
|
51
|
-
'text/plain ; charset="us-ascii"; another=opt').
|
52
|
-
|
50
|
+
expect(RestClient::Utils.cgi_parse_header(
|
51
|
+
'text/plain ; charset="us-ascii"; another=opt')).
|
52
|
+
to eq ['text/plain', {'charset' => 'us-ascii', 'another' => 'opt'}]
|
53
53
|
|
54
|
-
RestClient::Utils.cgi_parse_header(
|
55
|
-
'attachment; filename="silly.txt"').
|
56
|
-
|
54
|
+
expect(RestClient::Utils.cgi_parse_header(
|
55
|
+
'attachment; filename="silly.txt"')).
|
56
|
+
to eq ['attachment', {'filename' => 'silly.txt'}]
|
57
57
|
|
58
|
-
RestClient::Utils.cgi_parse_header(
|
59
|
-
'attachment; filename="strange;name"').
|
60
|
-
|
58
|
+
expect(RestClient::Utils.cgi_parse_header(
|
59
|
+
'attachment; filename="strange;name"')).
|
60
|
+
to eq ['attachment', {'filename' => 'strange;name'}]
|
61
61
|
|
62
|
-
RestClient::Utils.cgi_parse_header(
|
63
|
-
'attachment; filename="strange;name";size=123;').
|
62
|
+
expect(RestClient::Utils.cgi_parse_header(
|
63
|
+
'attachment; filename="strange;name";size=123;')).to eq \
|
64
64
|
['attachment', {'filename' => 'strange;name', 'size' => '123'}]
|
65
65
|
|
66
|
-
RestClient::Utils.cgi_parse_header(
|
67
|
-
'form-data; name="files"; filename="fo\\"o;bar"').
|
66
|
+
expect(RestClient::Utils.cgi_parse_header(
|
67
|
+
'form-data; name="files"; filename="fo\\"o;bar"')).to eq \
|
68
68
|
['form-data', {'name' => 'files', 'filename' => 'fo"o;bar'}]
|
69
69
|
end
|
70
70
|
end
|
71
|
+
|
72
|
+
describe '.encode_query_string' do
|
73
|
+
it 'handles simple hashes' do
|
74
|
+
{
|
75
|
+
{foo: 123, bar: 456} => 'foo=123&bar=456',
|
76
|
+
{'foo' => 123, 'bar' => 456} => 'foo=123&bar=456',
|
77
|
+
{foo: 'abc', bar: 'one two'} => 'foo=abc&bar=one+two',
|
78
|
+
{escaped: '1+2=3'} => 'escaped=1%2B2%3D3',
|
79
|
+
{'escaped + key' => 'foo'} => 'escaped+%2B+key=foo',
|
80
|
+
}.each_pair do |input, expected|
|
81
|
+
expect(RestClient::Utils.encode_query_string(input)).to eq expected
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'handles simple arrays' do
|
86
|
+
{
|
87
|
+
{foo: [1, 2, 3]} => 'foo[]=1&foo[]=2&foo[]=3',
|
88
|
+
{foo: %w{a b c}, bar: [1, 2, 3]} => 'foo[]=a&foo[]=b&foo[]=c&bar[]=1&bar[]=2&bar[]=3',
|
89
|
+
{foo: ['one two', 3]} => 'foo[]=one+two&foo[]=3',
|
90
|
+
{'a+b' => [1,2,3]} => 'a%2Bb[]=1&a%2Bb[]=2&a%2Bb[]=3',
|
91
|
+
}.each_pair do |input, expected|
|
92
|
+
expect(RestClient::Utils.encode_query_string(input)).to eq expected
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'handles nested hashes' do
|
97
|
+
{
|
98
|
+
{outer: {foo: 123, bar: 456}} => 'outer[foo]=123&outer[bar]=456',
|
99
|
+
{outer: {foo: [1, 2, 3], bar: 'baz'}} => 'outer[foo][]=1&outer[foo][]=2&outer[foo][]=3&outer[bar]=baz',
|
100
|
+
}.each_pair do |input, expected|
|
101
|
+
expect(RestClient::Utils.encode_query_string(input)).to eq expected
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'handles null and empty values' do
|
106
|
+
{
|
107
|
+
{string: '', empty: nil, list: [], hash: {}, falsey: false } =>
|
108
|
+
'string=&empty&list&hash&falsey=false',
|
109
|
+
}.each_pair do |input, expected|
|
110
|
+
expect(RestClient::Utils.encode_query_string(input)).to eq expected
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'handles nested nulls' do
|
115
|
+
{
|
116
|
+
{foo: {string: '', empty: nil}} => 'foo[string]=&foo[empty]',
|
117
|
+
}.each_pair do |input, expected|
|
118
|
+
expect(RestClient::Utils.encode_query_string(input)).to eq expected
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'handles deep nesting' do
|
123
|
+
{
|
124
|
+
{coords: [{x: 1, y: 0}, {x: 2}, {x: 3}]} => 'coords[][x]=1&coords[][y]=0&coords[][x]=2&coords[][x]=3',
|
125
|
+
}.each_pair do |input, expected|
|
126
|
+
expect(RestClient::Utils.encode_query_string(input)).to eq expected
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'handles multiple fields with the same name using ParamsArray' do
|
131
|
+
{
|
132
|
+
RestClient::ParamsArray.new([[:foo, 1], [:foo, 2], [:foo, 3]]) => 'foo=1&foo=2&foo=3',
|
133
|
+
}.each_pair do |input, expected|
|
134
|
+
expect(RestClient::Utils.encode_query_string(input)).to eq expected
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'handles nested ParamsArrays' do
|
139
|
+
{
|
140
|
+
{foo: RestClient::ParamsArray.new([[:a, 1], [:a, 2]])} => 'foo[a]=1&foo[a]=2',
|
141
|
+
RestClient::ParamsArray.new([[:foo, {a: 1}], [:foo, {a: 2}]]) => 'foo[a]=1&foo[a]=2',
|
142
|
+
}.each_pair do |input, expected|
|
143
|
+
expect(RestClient::Utils.encode_query_string(input)).to eq expected
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
71
147
|
end
|
@@ -5,7 +5,7 @@ describe 'RestClient::Windows::RootCerts',
|
|
5
5
|
let(:x509_store) { RestClient::Windows::RootCerts.instance.to_a }
|
6
6
|
|
7
7
|
it 'should return at least one X509 certificate' do
|
8
|
-
expect(x509_store.to_a).to
|
8
|
+
expect(x509_store.to_a.size).to be >= 1
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'should return an X509 certificate with a subject' do
|
@@ -16,7 +16,7 @@ describe 'RestClient::Windows::RootCerts',
|
|
16
16
|
|
17
17
|
it 'should return X509 certificate objects' do
|
18
18
|
x509_store.each do |cert|
|
19
|
-
cert.
|
19
|
+
expect(cert).to be_a(OpenSSL::X509::Certificate)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.rc3
|
5
5
|
platform: x64-mingw32
|
6
6
|
authors:
|
7
7
|
- REST Client Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-06-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: webmock
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '3.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: pry
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,7 +129,7 @@ dependencies:
|
|
129
129
|
version: '1.16'
|
130
130
|
- - "<"
|
131
131
|
- !ruby/object:Gem::Version
|
132
|
-
version: '
|
132
|
+
version: '4.0'
|
133
133
|
type: :runtime
|
134
134
|
prerelease: false
|
135
135
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -139,7 +139,7 @@ dependencies:
|
|
139
139
|
version: '1.16'
|
140
140
|
- - "<"
|
141
141
|
- !ruby/object:Gem::Version
|
142
|
-
version: '
|
142
|
+
version: '4.0'
|
143
143
|
- !ruby/object:Gem::Dependency
|
144
144
|
name: netrc
|
145
145
|
requirement: !ruby/object:Gem::Requirement
|
@@ -175,7 +175,7 @@ executables:
|
|
175
175
|
- restclient
|
176
176
|
extensions: []
|
177
177
|
extra_rdoc_files:
|
178
|
-
- README.
|
178
|
+
- README.md
|
179
179
|
- history.md
|
180
180
|
files:
|
181
181
|
- ".gitignore"
|
@@ -186,7 +186,7 @@ files:
|
|
186
186
|
- AUTHORS
|
187
187
|
- Gemfile
|
188
188
|
- LICENSE
|
189
|
-
- README.
|
189
|
+
- README.md
|
190
190
|
- Rakefile
|
191
191
|
- bin/restclient
|
192
192
|
- history.md
|
@@ -195,6 +195,7 @@ files:
|
|
195
195
|
- lib/restclient.rb
|
196
196
|
- lib/restclient/abstract_response.rb
|
197
197
|
- lib/restclient/exceptions.rb
|
198
|
+
- lib/restclient/params_array.rb
|
198
199
|
- lib/restclient/payload.rb
|
199
200
|
- lib/restclient/platform.rb
|
200
201
|
- lib/restclient/raw_response.rb
|
@@ -227,6 +228,7 @@ files:
|
|
227
228
|
- spec/unit/abstract_response_spec.rb
|
228
229
|
- spec/unit/exceptions_spec.rb
|
229
230
|
- spec/unit/master_shake.jpg
|
231
|
+
- spec/unit/params_array_spec.rb
|
230
232
|
- spec/unit/payload_spec.rb
|
231
233
|
- spec/unit/raw_response_spec.rb
|
232
234
|
- spec/unit/request2_spec.rb
|
@@ -248,7 +250,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
248
250
|
requirements:
|
249
251
|
- - ">="
|
250
252
|
- !ruby/object:Gem::Version
|
251
|
-
version:
|
253
|
+
version: 2.0.0
|
252
254
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
253
255
|
requirements:
|
254
256
|
- - ">"
|
@@ -256,7 +258,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
256
258
|
version: 1.3.1
|
257
259
|
requirements: []
|
258
260
|
rubyforge_project:
|
259
|
-
rubygems_version: 2.
|
261
|
+
rubygems_version: 2.4.5.1
|
260
262
|
signing_key:
|
261
263
|
specification_version: 4
|
262
264
|
summary: Simple HTTP and REST client for Ruby, inspired by microframework syntax for
|
@@ -282,6 +284,7 @@ test_files:
|
|
282
284
|
- spec/unit/abstract_response_spec.rb
|
283
285
|
- spec/unit/exceptions_spec.rb
|
284
286
|
- spec/unit/master_shake.jpg
|
287
|
+
- spec/unit/params_array_spec.rb
|
285
288
|
- spec/unit/payload_spec.rb
|
286
289
|
- spec/unit/raw_response_spec.rb
|
287
290
|
- spec/unit/request2_spec.rb
|
data/README.rdoc
DELETED
@@ -1,410 +0,0 @@
|
|
1
|
-
= REST Client -- simple DSL for accessing HTTP and REST resources
|
2
|
-
|
3
|
-
Build status: {<img src="https://travis-ci.org/rest-client/rest-client.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/rest-client/rest-client]
|
4
|
-
|
5
|
-
A simple HTTP and REST client for Ruby, inspired by the Sinatra's microframework style
|
6
|
-
of specifying actions: get, put, post, delete.
|
7
|
-
|
8
|
-
* Main page: https://github.com/rest-client/rest-client
|
9
|
-
* Mailing list: rest.client@librelist.com (send a mail to subscribe).
|
10
|
-
|
11
|
-
=== Mailing list changes
|
12
|
-
|
13
|
-
The Librelist mailing list is currently *defunct*, as Librelist appears to be
|
14
|
-
broken and not accepting new mail. We will choose a new email list provider
|
15
|
-
soon.
|
16
|
-
|
17
|
-
== Requirements
|
18
|
-
|
19
|
-
MRI Ruby 1.9.3 and newer are supported. Alternative interpreters compatible with
|
20
|
-
1.9+ should work as well.
|
21
|
-
|
22
|
-
Earlier Ruby versions such as 1.8.7 and 1.9.2 are no longer supported. These
|
23
|
-
versions no longer have any official support, and do not receive security
|
24
|
-
updates.
|
25
|
-
|
26
|
-
The rest-client gem depends on these other gems for usage at runtime:
|
27
|
-
|
28
|
-
* {mime-types}[http://rubygems.org/gems/mime-types]
|
29
|
-
* {netrc}[http://rubygems.org/gems/netrc]
|
30
|
-
* {http-cookie}[https://rubygems.org/gems/http-cookie]
|
31
|
-
|
32
|
-
There are also several development dependencies. It's recommended to use
|
33
|
-
{bundler}[http://bundler.io/] to manage these dependencies for hacking on
|
34
|
-
rest-client.
|
35
|
-
|
36
|
-
== Usage: Raw URL
|
37
|
-
|
38
|
-
require 'rest-client'
|
39
|
-
|
40
|
-
RestClient.get 'http://example.com/resource'
|
41
|
-
|
42
|
-
RestClient.get 'http://example.com/resource', {:params => {:id => 50, 'foo' => 'bar'}}
|
43
|
-
|
44
|
-
RestClient.get 'https://user:password@example.com/private/resource', {:accept => :json}
|
45
|
-
|
46
|
-
RestClient.post 'http://example.com/resource', :param1 => 'one', :nested => { :param2 => 'two' }
|
47
|
-
|
48
|
-
RestClient.post "http://example.com/resource", { 'x' => 1 }.to_json, :content_type => :json, :accept => :json
|
49
|
-
|
50
|
-
RestClient.delete 'http://example.com/resource'
|
51
|
-
|
52
|
-
response = RestClient.get 'http://example.com/resource'
|
53
|
-
response.code
|
54
|
-
➔ 200
|
55
|
-
response.cookies
|
56
|
-
➔ {"Foo"=>"BAR", "QUUX"=>"QUUUUX"}
|
57
|
-
response.headers
|
58
|
-
➔ {:content_type=>"text/html; charset=utf-8", :cache_control=>"private" ...
|
59
|
-
response.to_str
|
60
|
-
➔ \n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n \"http://www.w3.org/TR/html4/strict.dtd\">\n\n<html ....
|
61
|
-
|
62
|
-
RestClient.post( url,
|
63
|
-
{
|
64
|
-
:transfer => {
|
65
|
-
:path => '/foo/bar',
|
66
|
-
:owner => 'that_guy',
|
67
|
-
:group => 'those_guys'
|
68
|
-
},
|
69
|
-
:upload => {
|
70
|
-
:file => File.new(path, 'rb')
|
71
|
-
}
|
72
|
-
})
|
73
|
-
|
74
|
-
== Passing advanced options
|
75
|
-
|
76
|
-
The top level helper methods like RestClient.get accept a headers hash as
|
77
|
-
their last argument and don't allow passing more complex options. But these
|
78
|
-
helpers are just thin wrappers around RestClient::Request.execute.
|
79
|
-
|
80
|
-
RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
|
81
|
-
timeout: 10)
|
82
|
-
|
83
|
-
RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
|
84
|
-
ssl_ca_file: 'myca.pem',
|
85
|
-
ssl_ciphers: 'AESGCM:!aNULL')
|
86
|
-
|
87
|
-
You can also use this to pass a payload for HTTP verbs like DELETE, where the
|
88
|
-
RestClient.delete helper doesn't accept a payload.
|
89
|
-
|
90
|
-
RestClient::Request.execute(method: :delete, url: 'http://example.com/resource',
|
91
|
-
payload: 'foo', headers: {myheader: 'bar'})
|
92
|
-
|
93
|
-
Due to unfortunate choices in the original API, the params used to populate the
|
94
|
-
query string are actually taken out of the headers hash. So if you want to pass
|
95
|
-
both the params hash and more complex options, use the special key
|
96
|
-
<tt>:params</tt> in the headers hash. This design may change in a future major
|
97
|
-
release.
|
98
|
-
|
99
|
-
RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
|
100
|
-
timeout: 10, headers: {params: {foo: 'bar'}})
|
101
|
-
|
102
|
-
➔ GET http://example.com/resource?foo=bar
|
103
|
-
|
104
|
-
== Multipart
|
105
|
-
|
106
|
-
Yeah, that's right! This does multipart sends for you!
|
107
|
-
|
108
|
-
RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb')
|
109
|
-
|
110
|
-
This does two things for you:
|
111
|
-
|
112
|
-
* Auto-detects that you have a File value sends it as multipart
|
113
|
-
* Auto-detects the mime of the file and sets it in the HEAD of the payload for each entry
|
114
|
-
|
115
|
-
If you are sending params that do not contain a File object but the payload needs to be multipart then:
|
116
|
-
|
117
|
-
RestClient.post '/data', {:foo => 'bar', :multipart => true}
|
118
|
-
|
119
|
-
== Usage: ActiveResource-Style
|
120
|
-
|
121
|
-
resource = RestClient::Resource.new 'http://example.com/resource'
|
122
|
-
resource.get
|
123
|
-
|
124
|
-
private_resource = RestClient::Resource.new 'https://example.com/private/resource', 'user', 'pass'
|
125
|
-
private_resource.put File.read('pic.jpg'), :content_type => 'image/jpg'
|
126
|
-
|
127
|
-
See RestClient::Resource module docs for details.
|
128
|
-
|
129
|
-
== Usage: Resource Nesting
|
130
|
-
|
131
|
-
site = RestClient::Resource.new('http://example.com')
|
132
|
-
site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
133
|
-
|
134
|
-
See RestClient::Resource docs for details.
|
135
|
-
|
136
|
-
== Exceptions (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
|
137
|
-
|
138
|
-
* for result codes between 200 and 207, a RestClient::Response will be returned
|
139
|
-
* for result codes 301, 302 or 307, the redirection will be followed if the request is a GET or a HEAD
|
140
|
-
* for result code 303, the redirection will be followed and the request transformed into a GET
|
141
|
-
* for other cases, a RestClient::Exception holding the Response will be raised; a specific exception class will be thrown for known error codes
|
142
|
-
* call <tt>.response</tt> on the exception to get the server's response
|
143
|
-
|
144
|
-
RestClient.get 'http://example.com/resource'
|
145
|
-
➔ RestClient::ResourceNotFound: RestClient::ResourceNotFound
|
146
|
-
|
147
|
-
begin
|
148
|
-
RestClient.get 'http://example.com/resource'
|
149
|
-
rescue => e
|
150
|
-
e.response
|
151
|
-
end
|
152
|
-
➔ 404 Resource Not Found | text/html 282 bytes
|
153
|
-
|
154
|
-
== Result handling
|
155
|
-
|
156
|
-
The result of a RestClient::Request is a RestClient::Response object.
|
157
|
-
|
158
|
-
<b>New in 2.0:</b> RestClient::Response objects are now a subclass of String.
|
159
|
-
Previously, they were a real String object with response functionality mixed
|
160
|
-
in, which was very confusing to work with.
|
161
|
-
|
162
|
-
Response objects have several useful methods. (See the class rdoc for more details.)
|
163
|
-
|
164
|
-
* Response#code: The HTTP response code
|
165
|
-
* Response#body: The response body as a string. (AKA .to_s)
|
166
|
-
* Response#headers: A hash of HTTP response headers
|
167
|
-
* Response#cookies: A hash of HTTP cookies set by the server
|
168
|
-
* Response#cookie_jar: <em>New in 1.8</em> An HTTP::CookieJar of cookies
|
169
|
-
* Response#request: The RestClient::Request object used to make the request
|
170
|
-
* Response#history: If redirection was followed, a list of prior Response objects
|
171
|
-
|
172
|
-
>> RestClient.get('http://example.com')
|
173
|
-
=> <RestClient::Response 200 "<!doctype h...">
|
174
|
-
|
175
|
-
>> begin
|
176
|
-
>> RestClient.get('http://example.com/notfound')
|
177
|
-
>> rescue RestClient::ExceptionWithResponse => err
|
178
|
-
>> err.response
|
179
|
-
>> end
|
180
|
-
=> <RestClient::Response 404 "<!doctype h...">
|
181
|
-
|
182
|
-
=== Response callbacks
|
183
|
-
|
184
|
-
A block can be passed to the RestClient method. This block will then be called with the Response.
|
185
|
-
Response.return! can be called to invoke the default response's behavior.
|
186
|
-
|
187
|
-
# Don't raise exceptions but return the response
|
188
|
-
RestClient.get('http://example.com/resource'){|response, request, result| response }
|
189
|
-
➔ 404 Resource Not Found | text/html 282 bytes
|
190
|
-
|
191
|
-
# Manage a specific error code
|
192
|
-
RestClient.get('http://my-rest-service.com/resource'){ |response, request, result, &block|
|
193
|
-
case response.code
|
194
|
-
when 200
|
195
|
-
p "It worked !"
|
196
|
-
response
|
197
|
-
when 423
|
198
|
-
raise SomeCustomExceptionIfYouWant
|
199
|
-
else
|
200
|
-
response.return!(request, result, &block)
|
201
|
-
end
|
202
|
-
}
|
203
|
-
|
204
|
-
# Follow redirections for all request types and not only for get and head
|
205
|
-
# RFC : "If the 301, 302 or 307 status code is received in response to a request other than GET or HEAD,
|
206
|
-
# the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user,
|
207
|
-
# since this might change the conditions under which the request was issued."
|
208
|
-
RestClient.get('http://my-rest-service.com/resource'){ |response, request, result, &block|
|
209
|
-
if [301, 302, 307].include? response.code
|
210
|
-
response.follow_redirection(request, result, &block)
|
211
|
-
else
|
212
|
-
response.return!(request, result, &block)
|
213
|
-
end
|
214
|
-
}
|
215
|
-
|
216
|
-
== Non-normalized URIs
|
217
|
-
|
218
|
-
If you need to normalize URIs, e.g. to work with International Resource Identifiers (IRIs),
|
219
|
-
use the addressable gem (http://addressable.rubyforge.org/api/) in your code:
|
220
|
-
|
221
|
-
require 'addressable/uri'
|
222
|
-
RestClient.get(Addressable::URI.parse("http://www.詹姆斯.com/").normalize.to_str)
|
223
|
-
|
224
|
-
== Lower-level access
|
225
|
-
|
226
|
-
For cases not covered by the general API, you can use the RestClient::Request class, which provides a lower-level API.
|
227
|
-
|
228
|
-
You can:
|
229
|
-
|
230
|
-
* specify ssl parameters
|
231
|
-
* override cookies
|
232
|
-
* manually handle the response (e.g. to operate on it as a stream rather than reading it all into memory)
|
233
|
-
|
234
|
-
See RestClient::Request's documentation for more information.
|
235
|
-
|
236
|
-
== Shell
|
237
|
-
|
238
|
-
The restclient shell command gives an IRB session with RestClient already loaded:
|
239
|
-
|
240
|
-
$ restclient
|
241
|
-
>> RestClient.get 'http://example.com'
|
242
|
-
|
243
|
-
Specify a URL argument for get/post/put/delete on that resource:
|
244
|
-
|
245
|
-
$ restclient http://example.com
|
246
|
-
>> put '/resource', 'data'
|
247
|
-
|
248
|
-
Add a user and password for authenticated resources:
|
249
|
-
|
250
|
-
$ restclient https://example.com user pass
|
251
|
-
>> delete '/private/resource'
|
252
|
-
|
253
|
-
Create ~/.restclient for named sessions:
|
254
|
-
|
255
|
-
sinatra:
|
256
|
-
url: http://localhost:4567
|
257
|
-
rack:
|
258
|
-
url: http://localhost:9292
|
259
|
-
private_site:
|
260
|
-
url: http://example.com
|
261
|
-
username: user
|
262
|
-
password: pass
|
263
|
-
|
264
|
-
Then invoke:
|
265
|
-
|
266
|
-
$ restclient private_site
|
267
|
-
|
268
|
-
Use as a one-off, curl-style:
|
269
|
-
|
270
|
-
$ restclient get http://example.com/resource > output_body
|
271
|
-
|
272
|
-
$ restclient put http://example.com/resource < input_body
|
273
|
-
|
274
|
-
== Logging
|
275
|
-
|
276
|
-
To enable logging you can:
|
277
|
-
|
278
|
-
* set RestClient.log with a Ruby Logger, or
|
279
|
-
* set an environment variable to avoid modifying the code (in this case you can use a file name, "stdout" or "stderr"):
|
280
|
-
|
281
|
-
$ RESTCLIENT_LOG=stdout path/to/my/program
|
282
|
-
|
283
|
-
Either produces logs like this:
|
284
|
-
|
285
|
-
RestClient.get "http://some/resource"
|
286
|
-
# => 200 OK | text/html 250 bytes
|
287
|
-
RestClient.put "http://some/resource", "payload"
|
288
|
-
# => 401 Unauthorized | application/xml 340 bytes
|
289
|
-
|
290
|
-
Note that these logs are valid Ruby, so you can paste them into the restclient
|
291
|
-
shell or a script to replay your sequence of rest calls.
|
292
|
-
|
293
|
-
== Proxy
|
294
|
-
|
295
|
-
All calls to RestClient, including Resources, will use the proxy specified by
|
296
|
-
RestClient.proxy:
|
297
|
-
|
298
|
-
RestClient.proxy = "http://proxy.example.com/"
|
299
|
-
RestClient.get "http://some/resource"
|
300
|
-
# => response from some/resource as proxied through proxy.example.com
|
301
|
-
|
302
|
-
Often the proxy URL is set in an environment variable, so you can do this to
|
303
|
-
use whatever proxy the system is configured to use:
|
304
|
-
|
305
|
-
RestClient.proxy = ENV['http_proxy']
|
306
|
-
|
307
|
-
== Query parameters
|
308
|
-
|
309
|
-
Request objects know about query parameters and will automatically add them to
|
310
|
-
the URL for GET, HEAD and DELETE requests, escaping the keys and values as needed:
|
311
|
-
|
312
|
-
RestClient.get 'http://example.com/resource', :params => {:foo => 'bar', :baz => 'qux'}
|
313
|
-
# will GET http://example.com/resource?foo=bar&baz=qux
|
314
|
-
|
315
|
-
== Headers
|
316
|
-
|
317
|
-
Request headers can be set by passing a ruby hash containing keys and values
|
318
|
-
representing header names and values:
|
319
|
-
|
320
|
-
# GET request with modified headers
|
321
|
-
RestClient.get 'http://example.com/resource', {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
|
322
|
-
|
323
|
-
# POST request with modified headers
|
324
|
-
RestClient.post 'http://example.com/resource', {:foo => 'bar', :baz => 'qux'}, {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
|
325
|
-
|
326
|
-
# DELETE request with modified headers
|
327
|
-
RestClient.delete 'http://example.com/resource', {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
|
328
|
-
|
329
|
-
== Cookies
|
330
|
-
|
331
|
-
Request and Response objects know about HTTP cookies, and will automatically
|
332
|
-
extract and set headers for them as needed:
|
333
|
-
|
334
|
-
response = RestClient.get 'http://example.com/action_which_sets_session_id'
|
335
|
-
response.cookies
|
336
|
-
# => {"_applicatioN_session_id" => "1234"}
|
337
|
-
|
338
|
-
response2 = RestClient.post(
|
339
|
-
'http://localhost:3000/',
|
340
|
-
{:param1 => "foo"},
|
341
|
-
{:cookies => {:session_id => "1234"}}
|
342
|
-
)
|
343
|
-
# ...response body
|
344
|
-
|
345
|
-
== SSL/TLS support
|
346
|
-
|
347
|
-
Various options are supported for configuring rest-client's TLS settings. By
|
348
|
-
default, rest-client will verify certificates using the system's CA store on
|
349
|
-
all platforms. (This is intended to be similar to how browsers behave.) You can
|
350
|
-
specify an :ssl_ca_file, :ssl_ca_path, or :ssl_cert_store to customize the
|
351
|
-
certificate authorities accepted.
|
352
|
-
|
353
|
-
=== SSL Client Certificates
|
354
|
-
|
355
|
-
RestClient::Resource.new(
|
356
|
-
'https://example.com',
|
357
|
-
:ssl_client_cert => OpenSSL::X509::Certificate.new(File.read("cert.pem")),
|
358
|
-
:ssl_client_key => OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
|
359
|
-
:ssl_ca_file => "ca_certificate.pem",
|
360
|
-
:verify_ssl => OpenSSL::SSL::VERIFY_PEER
|
361
|
-
).get
|
362
|
-
|
363
|
-
Self-signed certificates can be generated with the openssl command-line tool.
|
364
|
-
|
365
|
-
== Hook
|
366
|
-
|
367
|
-
RestClient.add_before_execution_proc add a Proc to be called before each execution.
|
368
|
-
It's handy if you need direct access to the HTTP request.
|
369
|
-
|
370
|
-
Example:
|
371
|
-
|
372
|
-
# Add oauth support using the oauth gem
|
373
|
-
require 'oauth'
|
374
|
-
access_token = ...
|
375
|
-
|
376
|
-
RestClient.add_before_execution_proc do |req, params|
|
377
|
-
access_token.sign! req
|
378
|
-
end
|
379
|
-
|
380
|
-
RestClient.get 'http://example.com'
|
381
|
-
|
382
|
-
== More
|
383
|
-
|
384
|
-
Need caching, more advanced logging or any ability provided by Rack middleware?
|
385
|
-
|
386
|
-
Have a look at rest-client-components: http://github.com/crohr/rest-client-components
|
387
|
-
|
388
|
-
== Credits
|
389
|
-
|
390
|
-
REST Client Team:: Andy Brody
|
391
|
-
|
392
|
-
Creator:: Adam Wiggins
|
393
|
-
|
394
|
-
Maintainers Emeriti:: Lawrence Leonard Gilbert, Matthew Manning, Julien Kirch
|
395
|
-
|
396
|
-
Major contributions:: Blake Mizerany, Julien Kirch
|
397
|
-
|
398
|
-
A great many generous folks have contributed features and patches.
|
399
|
-
See AUTHORS for the full list.
|
400
|
-
|
401
|
-
== Legal
|
402
|
-
|
403
|
-
Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
|
404
|
-
|
405
|
-
"Master Shake" photo (http://www.flickr.com/photos/solgrundy/924205581/) by
|
406
|
-
"SolGrundy"; used under terms of the Creative Commons Attribution-ShareAlike 2.0
|
407
|
-
Generic license (http://creativecommons.org/licenses/by-sa/2.0/)
|
408
|
-
|
409
|
-
Code for reading Windows root certificate store derived from work by Puppet;
|
410
|
-
used under terms of the Apache License, Version 2.0.
|