rest-client 1.6.7 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.mailmap +10 -0
  4. data/.rspec +2 -0
  5. data/.rubocop +2 -0
  6. data/.rubocop-disables.yml +386 -0
  7. data/.rubocop.yml +8 -0
  8. data/.travis.yml +62 -0
  9. data/AUTHORS +106 -0
  10. data/Gemfile +11 -0
  11. data/LICENSE +21 -0
  12. data/README.md +901 -0
  13. data/Rakefile +109 -35
  14. data/bin/restclient +11 -12
  15. data/history.md +244 -1
  16. data/lib/restclient.rb +27 -18
  17. data/lib/restclient/abstract_response.rb +197 -51
  18. data/lib/restclient/exceptions.rb +110 -59
  19. data/lib/restclient/params_array.rb +72 -0
  20. data/lib/restclient/payload.rb +74 -75
  21. data/lib/restclient/platform.rb +49 -0
  22. data/lib/restclient/raw_response.rb +21 -6
  23. data/lib/restclient/request.rb +747 -183
  24. data/lib/restclient/resource.rb +22 -13
  25. data/lib/restclient/response.rb +75 -9
  26. data/lib/restclient/utils.rb +274 -0
  27. data/lib/restclient/version.rb +8 -0
  28. data/lib/restclient/windows.rb +8 -0
  29. data/lib/restclient/windows/root_certs.rb +105 -0
  30. data/rest-client.gemspec +32 -0
  31. data/rest-client.windows.gemspec +19 -0
  32. data/spec/ISS.jpg +0 -0
  33. data/spec/helpers.rb +54 -0
  34. data/spec/integration/_lib.rb +1 -0
  35. data/spec/integration/capath_digicert/3513523f.0 +22 -0
  36. data/spec/integration/capath_digicert/399e7759.0 +22 -0
  37. data/spec/integration/capath_digicert/README +8 -0
  38. data/spec/integration/capath_digicert/digicert.crt +22 -0
  39. data/spec/integration/capath_verisign/415660c1.0 +14 -0
  40. data/spec/integration/capath_verisign/7651b327.0 +14 -0
  41. data/spec/integration/capath_verisign/README +8 -0
  42. data/spec/integration/capath_verisign/verisign.crt +14 -0
  43. data/spec/integration/certs/digicert.crt +22 -0
  44. data/spec/integration/httpbin_spec.rb +128 -0
  45. data/spec/integration/integration_spec.rb +118 -0
  46. data/spec/integration/request_spec.rb +109 -7
  47. data/spec/spec_helper.rb +29 -0
  48. data/spec/unit/_lib.rb +1 -0
  49. data/spec/unit/abstract_response_spec.rb +145 -0
  50. data/spec/unit/exceptions_spec.rb +108 -0
  51. data/spec/unit/params_array_spec.rb +36 -0
  52. data/spec/unit/payload_spec.rb +295 -0
  53. data/spec/unit/raw_response_spec.rb +22 -0
  54. data/spec/unit/request2_spec.rb +54 -0
  55. data/spec/unit/request_spec.rb +1238 -0
  56. data/spec/unit/resource_spec.rb +134 -0
  57. data/spec/unit/response_spec.rb +252 -0
  58. data/spec/unit/restclient_spec.rb +80 -0
  59. data/spec/unit/utils_spec.rb +147 -0
  60. data/spec/unit/windows/root_certs_spec.rb +22 -0
  61. metadata +265 -117
  62. data/README.rdoc +0 -285
  63. data/VERSION +0 -1
  64. data/lib/restclient/net_http_ext.rb +0 -55
  65. data/spec/abstract_response_spec.rb +0 -85
  66. data/spec/base.rb +0 -16
  67. data/spec/exceptions_spec.rb +0 -98
  68. data/spec/integration/certs/equifax.crt +0 -19
  69. data/spec/integration_spec.rb +0 -38
  70. data/spec/master_shake.jpg +0 -0
  71. data/spec/payload_spec.rb +0 -234
  72. data/spec/raw_response_spec.rb +0 -17
  73. data/spec/request2_spec.rb +0 -40
  74. data/spec/request_spec.rb +0 -529
  75. data/spec/resource_spec.rb +0 -134
  76. data/spec/response_spec.rb +0 -169
  77. data/spec/restclient_spec.rb +0 -73
data/README.rdoc DELETED
@@ -1,285 +0,0 @@
1
- = REST Client -- simple DSL for accessing HTTP and REST resources
2
-
3
- A simple HTTP and REST client for Ruby, inspired by the Sinatra's microframework style
4
- of specifying actions: get, put, post, delete.
5
-
6
- * Main page: http://github.com/archiloque/rest-client
7
- * Mailing list: rest.client@librelist.com (send a mail to subscribe).
8
-
9
- == Usage: Raw URL
10
-
11
- require 'rest_client'
12
-
13
- RestClient.get 'http://example.com/resource'
14
-
15
- RestClient.get 'http://example.com/resource', {:params => {:id => 50, 'foo' => 'bar'}}
16
-
17
- RestClient.get 'https://user:password@example.com/private/resource', {:accept => :json}
18
-
19
- RestClient.post 'http://example.com/resource', :param1 => 'one', :nested => { :param2 => 'two' }
20
-
21
- RestClient.post "http://example.com/resource", { 'x' => 1 }.to_json, :content_type => :json, :accept => :json
22
-
23
- RestClient.delete 'http://example.com/resource'
24
-
25
- response = RestClient.get 'http://example.com/resource'
26
- response.code
27
- ➔ 200
28
- response.cookies
29
- ➔ {"Foo"=>"BAR", "QUUX"=>"QUUUUX"}
30
- response.headers
31
- ➔ {:content_type=>"text/html; charset=utf-8", :cache_control=>"private" ...
32
- response.to_str
33
- ➔ \n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n \"http://www.w3.org/TR/html4/strict.dtd\">\n\n<html ....
34
-
35
- RestClient.post( url,
36
- {
37
- :transfer => {
38
- :path => '/foo/bar',
39
- :owner => 'that_guy',
40
- :group => 'those_guys'
41
- },
42
- :upload => {
43
- :file => File.new(path, 'rb')
44
- }
45
- })
46
-
47
- == Multipart
48
-
49
- Yeah, that's right! This does multipart sends for you!
50
-
51
- RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb')
52
-
53
- This does two things for you:
54
-
55
- * Auto-detects that you have a File value sends it as multipart
56
- * Auto-detects the mime of the file and sets it in the HEAD of the payload for each entry
57
-
58
- If you are sending params that do not contain a File object but the payload needs to be multipart then:
59
-
60
- RestClient.post '/data', :foo => 'bar', :multipart => true
61
-
62
- == Usage: ActiveResource-Style
63
-
64
- resource = RestClient::Resource.new 'http://example.com/resource'
65
- resource.get
66
-
67
- private_resource = RestClient::Resource.new 'https://example.com/private/resource', 'user', 'pass'
68
- private_resource.put File.read('pic.jpg'), :content_type => 'image/jpg'
69
-
70
- See RestClient::Resource module docs for details.
71
-
72
- == Usage: Resource Nesting
73
-
74
- site = RestClient::Resource.new('http://example.com')
75
- site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
76
-
77
- See RestClient::Resource docs for details.
78
-
79
- == Exceptions (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
80
-
81
- * for results code between 200 and 207 a RestClient::Response will be returned
82
- * for results code 301, 302 or 307 the redirection will be followed if the request is a get or a head
83
- * for result code 303 the redirection will be followed and the request transformed into a get
84
- * for other cases a RestClient::Exception holding the Response will be raised, a specific exception class will be thrown for know error codes
85
-
86
- RestClient.get 'http://example.com/resource'
87
- ➔ RestClient::ResourceNotFound: RestClient::ResourceNotFound
88
-
89
- begin
90
- RestClient.get 'http://example.com/resource'
91
- rescue => e
92
- e.response
93
- end
94
- ➔ 404 Resource Not Found | text/html 282 bytes
95
-
96
- == Result handling
97
-
98
- A block can be passed to the RestClient method, this block will then be called with the Response.
99
- Response.return! can be called to invoke the default response's behavior.
100
-
101
- # Don't raise exceptions but return the response
102
- RestClient.get('http://example.com/resource'){|response, request, result| response }
103
- ➔ 404 Resource Not Found | text/html 282 bytes
104
-
105
- # Manage a specific error code
106
- RestClient.get('http://my-rest-service.com/resource'){ |response, request, result, &block|
107
- case response.code
108
- when 200
109
- p "It worked !"
110
- response
111
- when 423
112
- raise SomeCustomExceptionIfYouWant
113
- else
114
- response.return!(request, result, &block)
115
- end
116
- }
117
-
118
- # Follow redirections for all request types and not only for get and head
119
- # RFC : "If the 301, 302 or 307 status code is received in response to a request other than GET or HEAD,
120
- # the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user,
121
- # since this might change the conditions under which the request was issued."
122
- RestClient.get('http://my-rest-service.com/resource'){ |response, request, result, &block|
123
- if [301, 302, 307].include? response.code
124
- response.follow_redirection(request, result, &block)
125
- else
126
- response.return!(request, result, &block)
127
- end
128
- }
129
-
130
- == Non-normalized URIs.
131
-
132
- If you want to use non-normalized URIs, you can normalize them with the addressable gem (http://addressable.rubyforge.org/api/).
133
-
134
- require 'addressable/uri'
135
- RestClient.get(Addressable::URI.parse("http://www.詹姆斯.com/").normalize.to_str)
136
-
137
- == Lower-level access
138
-
139
- For cases not covered by the general API, you can use the RestClient::Request class which provide a lower-level API.
140
-
141
- You can:
142
-
143
- * specify ssl parameters
144
- * override cookies
145
- * manually handle the response (so you can operate on the response stream than reading it fully in memory)
146
-
147
- see the class' rdoc for more information.
148
-
149
- == Shell
150
-
151
- The restclient shell command gives an IRB session with RestClient already loaded:
152
-
153
- $ restclient
154
- >> RestClient.get 'http://example.com'
155
-
156
- Specify a URL argument for get/post/put/delete on that resource:
157
-
158
- $ restclient http://example.com
159
- >> put '/resource', 'data'
160
-
161
- Add a user and password for authenticated resources:
162
-
163
- $ restclient https://example.com user pass
164
- >> delete '/private/resource'
165
-
166
- Create ~/.restclient for named sessions:
167
-
168
- sinatra:
169
- url: http://localhost:4567
170
- rack:
171
- url: http://localhost:9292
172
- private_site:
173
- url: http://example.com
174
- username: user
175
- password: pass
176
-
177
- Then invoke:
178
-
179
- $ restclient private_site
180
-
181
- Use as a one-off, curl-style:
182
-
183
- $ restclient get http://example.com/resource > output_body
184
-
185
- $ restclient put http://example.com/resource < input_body
186
-
187
- == Logging
188
-
189
- To enable logging you can
190
-
191
- * set RestClient.log with a ruby Logger
192
- * or set an environment variable to avoid modifying the code (in this case you can use a file name, "stdout" or "stderr"):
193
-
194
- $ RESTCLIENT_LOG=stdout path/to/my/program
195
-
196
- Either produces logs like this:
197
-
198
- RestClient.get "http://some/resource"
199
- # => 200 OK | text/html 250 bytes
200
- RestClient.put "http://some/resource", "payload"
201
- # => 401 Unauthorized | application/xml 340 bytes
202
-
203
- Note that these logs are valid Ruby, so you can paste them into the restclient
204
- shell or a script to replay your sequence of rest calls.
205
-
206
- == Proxy
207
-
208
- All calls to RestClient, including Resources, will use the proxy specified by
209
- RestClient.proxy:
210
-
211
- RestClient.proxy = "http://proxy.example.com/"
212
- RestClient.get "http://some/resource"
213
- # => response from some/resource as proxied through proxy.example.com
214
-
215
- Often the proxy url is set in an environment variable, so you can do this to
216
- use whatever proxy the system is configured to use:
217
-
218
- RestClient.proxy = ENV['http_proxy']
219
-
220
- == Query parameters
221
-
222
- Request objects know about query parameters and will automatically add them to
223
- the url for GET, HEAD and DELETE requests and escape the keys and values as
224
- needed:
225
-
226
- RestClient.get 'http://example.com/resource', :params => {:foo => 'bar', :baz => 'qux'}
227
- # will GET http://example.com/resource?foo=bar&baz=qux
228
-
229
- == Cookies
230
-
231
- Request and Response objects know about HTTP cookies, and will automatically
232
- extract and set headers for them as needed:
233
-
234
- response = RestClient.get 'http://example.com/action_which_sets_session_id'
235
- response.cookies
236
- # => {"_applicatioN_session_id" => "1234"}
237
-
238
- response2 = RestClient.post(
239
- 'http://localhost:3000/',
240
- {:param1 => "foo"},
241
- {:cookies => {:session_id => "1234"}}
242
- )
243
- # ...response body
244
-
245
- == SSL Client Certificates
246
-
247
- RestClient::Resource.new(
248
- 'https://example.com',
249
- :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read("cert.pem")),
250
- :ssl_client_key => OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
251
- :ssl_ca_file => "ca_certificate.pem",
252
- :verify_ssl => OpenSSL::SSL::VERIFY_PEER
253
- ).get
254
-
255
- Self-signed certificates can be generated with the openssl command-line tool.
256
-
257
- == Hook
258
-
259
- RestClient.add_before_execution_proc add a Proc to be called before each execution, it's handy if you need a direct access to the http request.
260
-
261
- Example:
262
-
263
- # Add oath support using the oauth gem
264
- require 'oauth'
265
- access_token = ...
266
-
267
- RestClient.add_before_execution_proc do |req, params|
268
- access_token.sign! req
269
- end
270
-
271
- RestClient.get 'http://example.com'
272
-
273
- == More
274
-
275
- Need caching, more advanced logging or any ability provided by a rack middleware ?
276
-
277
- Have a look at rest-client-components http://github.com/crohr/rest-client-components
278
-
279
- == Meta
280
-
281
- Written by Adam Wiggins, major modifications by Blake Mizerany, maintained by Julien Kirch
282
-
283
- Patches contributed by many, including Chris Anderson, Greg Borenstein, Ardekantur, Pedro Belo, Rafael Souza, Rick Olson, Aman Gupta, François Beausoleil and Nick Plante.
284
-
285
- Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.6.6
@@ -1,55 +0,0 @@
1
- module Net
2
- class HTTP
3
-
4
- # Adding the patch method if it doesn't exist (rest-client issue: https://github.com/archiloque/rest-client/issues/79)
5
- if !defined?(Net::HTTP::Patch)
6
- # Code taken from this commit: https://github.com/ruby/ruby/commit/ab70e53ac3b5102d4ecbe8f38d4f76afad29d37d#lib/net/http.rb
7
- class Protocol
8
- # Sends a PATCH request to the +path+ and gets a response,
9
- # as an HTTPResponse object.
10
- def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
11
- send_entity(path, data, initheader, dest, Patch, &block)
12
- end
13
-
14
- # Executes a request which uses a representation
15
- # and returns its body.
16
- def send_entity(path, data, initheader, dest, type, &block)
17
- res = nil
18
- request(type.new(path, initheader), data) {|r|
19
- r.read_body dest, &block
20
- res = r
21
- }
22
- unless @newimpl
23
- res.value
24
- return res, res.body
25
- end
26
- res
27
- end
28
- end
29
-
30
- class Patch < HTTPRequest
31
- METHOD = 'PATCH'
32
- REQUEST_HAS_BODY = true
33
- RESPONSE_HAS_BODY = true
34
- end
35
- end
36
-
37
- #
38
- # Replace the request method in Net::HTTP to sniff the body type
39
- # and set the stream if appropriate
40
- #
41
- # Taken from:
42
- # http://www.missiondata.com/blog/ruby/29/streaming-data-to-s3-with-ruby/
43
-
44
- alias __request__ request
45
-
46
- def request(req, body=nil, &block)
47
- if body != nil && body.respond_to?(:read)
48
- req.body_stream = body
49
- return __request__(req, nil, &block)
50
- else
51
- return __request__(req, body, &block)
52
- end
53
- end
54
- end
55
- end
@@ -1,85 +0,0 @@
1
- require File.join( File.dirname(File.expand_path(__FILE__)), 'base')
2
-
3
- describe RestClient::AbstractResponse do
4
-
5
- class MyAbstractResponse
6
-
7
- include RestClient::AbstractResponse
8
-
9
- attr_accessor :size
10
-
11
- def initialize net_http_res, args
12
- @net_http_res = net_http_res
13
- @args = args
14
- end
15
-
16
- end
17
-
18
- before do
19
- @net_http_res = mock('net http response')
20
- @response = MyAbstractResponse.new(@net_http_res, {})
21
- end
22
-
23
- it "fetches the numeric response code" do
24
- @net_http_res.should_receive(:code).and_return('200')
25
- @response.code.should == 200
26
- end
27
-
28
- it "has a nice description" do
29
- @net_http_res.should_receive(:to_hash).and_return({'Content-Type' => ['application/pdf']})
30
- @net_http_res.should_receive(:code).and_return('200')
31
- @response.description == '200 OK | application/pdf bytes\n'
32
- end
33
-
34
- it "beautifies the headers by turning the keys to symbols" do
35
- h = RestClient::AbstractResponse.beautify_headers('content-type' => [ 'x' ])
36
- h.keys.first.should == :content_type
37
- end
38
-
39
- it "beautifies the headers by turning the values to strings instead of one-element arrays" do
40
- h = RestClient::AbstractResponse.beautify_headers('x' => [ 'text/html' ] )
41
- h.values.first.should == 'text/html'
42
- end
43
-
44
- it "fetches the headers" do
45
- @net_http_res.should_receive(:to_hash).and_return('content-type' => [ 'text/html' ])
46
- @response.headers.should == { :content_type => 'text/html' }
47
- end
48
-
49
- it "extracts cookies from response headers" do
50
- @net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=1; path=/'])
51
- @response.cookies.should == { 'session_id' => '1' }
52
- end
53
-
54
- it "extract strange cookies" do
55
- @net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=ZJ/HQVH6YE+rVkTpn0zvTQ==; path=/'])
56
- @response.cookies.should == { 'session_id' => 'ZJ%2FHQVH6YE+rVkTpn0zvTQ%3D%3D' }
57
- end
58
-
59
- it "doesn't escape cookies" do
60
- @net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=BAh7BzoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOgpsb2dpbiIKYWRtaW4%3D%0A--08114ba654f17c04d20dcc5228ec672508f738ca; path=/'])
61
- @response.cookies.should == { 'session_id' => 'BAh7BzoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOgpsb2dpbiIKYWRtaW4%3D%0A--08114ba654f17c04d20dcc5228ec672508f738ca' }
62
- end
63
-
64
- it "can access the net http result directly" do
65
- @response.net_http_res.should == @net_http_res
66
- end
67
-
68
- describe "#return!" do
69
- it "should return the response itself on 200-codes" do
70
- @net_http_res.should_receive(:code).and_return('200')
71
- @response.return!.should be_equal(@response)
72
- end
73
-
74
- it "should raise RequestFailed on unknown codes" do
75
- @net_http_res.should_receive(:code).and_return('1000')
76
- lambda { @response.return! }.should raise_error RestClient::RequestFailed
77
- end
78
-
79
- it "should raise an error on a redirection after non-GET/HEAD requests" do
80
- @net_http_res.should_receive(:code).and_return('301')
81
- @response.args.merge(:method => :put)
82
- lambda { @response.return! }.should raise_error RestClient::RequestFailed
83
- end
84
- end
85
- end
data/spec/base.rb DELETED
@@ -1,16 +0,0 @@
1
- def is_ruby_19?
2
- RUBY_VERSION == '1.9.1' or RUBY_VERSION == '1.9.2'
3
- end
4
-
5
- Encoding.default_internal = Encoding.default_external = "ASCII-8BIT" if is_ruby_19?
6
-
7
- require 'rubygems'
8
- require 'spec'
9
-
10
- begin
11
- require "ruby-debug"
12
- rescue LoadError
13
- # NOP, ignore
14
- end
15
-
16
- require File.dirname(__FILE__) + '/../lib/restclient'
@@ -1,98 +0,0 @@
1
- require File.join( File.dirname(File.expand_path(__FILE__)), 'base')
2
-
3
- require 'webmock/rspec'
4
- include WebMock
5
-
6
- describe RestClient::Exception do
7
- it "returns a 'message' equal to the class name if the message is not set, because 'message' should not be nil" do
8
- e = RestClient::Exception.new
9
- e.message.should == "RestClient::Exception"
10
- end
11
-
12
- it "returns the 'message' that was set" do
13
- e = RestClient::Exception.new
14
- message = "An explicitly set message"
15
- e.message = message
16
- e.message.should == message
17
- end
18
-
19
- it "sets the exception message to ErrorMessage" do
20
- RestClient::ResourceNotFound.new.message.should == 'Resource Not Found'
21
- end
22
-
23
- it "contains exceptions in RestClient" do
24
- RestClient::Unauthorized.new.should be_a_kind_of(RestClient::Exception)
25
- RestClient::ServerBrokeConnection.new.should be_a_kind_of(RestClient::Exception)
26
- end
27
- end
28
-
29
- describe RestClient::ServerBrokeConnection do
30
- it "should have a default message of 'Server broke connection'" do
31
- e = RestClient::ServerBrokeConnection.new
32
- e.message.should == 'Server broke connection'
33
- end
34
- end
35
-
36
- describe RestClient::RequestFailed do
37
- before do
38
- @response = mock('HTTP Response', :code => '502')
39
- end
40
-
41
- it "stores the http response on the exception" do
42
- response = "response"
43
- begin
44
- raise RestClient::RequestFailed, response
45
- rescue RestClient::RequestFailed => e
46
- e.response.should == response
47
- end
48
- end
49
-
50
- it "http_code convenience method for fetching the code as an integer" do
51
- RestClient::RequestFailed.new(@response).http_code.should == 502
52
- end
53
-
54
- it "http_body convenience method for fetching the body (decoding when necessary)" do
55
- RestClient::RequestFailed.new(@response).http_code.should == 502
56
- RestClient::RequestFailed.new(@response).message.should == 'HTTP status code 502'
57
- end
58
-
59
- it "shows the status code in the message" do
60
- RestClient::RequestFailed.new(@response).to_s.should match(/502/)
61
- end
62
- end
63
-
64
- describe RestClient::ResourceNotFound do
65
- it "also has the http response attached" do
66
- response = "response"
67
- begin
68
- raise RestClient::ResourceNotFound, response
69
- rescue RestClient::ResourceNotFound => e
70
- e.response.should == response
71
- end
72
- end
73
- end
74
-
75
- describe "backwards compatibility" do
76
- it "alias RestClient::Request::Redirect to RestClient::Redirect" do
77
- RestClient::Request::Redirect.should == RestClient::Redirect
78
- end
79
-
80
- it "alias RestClient::Request::Unauthorized to RestClient::Unauthorized" do
81
- RestClient::Request::Unauthorized.should == RestClient::Unauthorized
82
- end
83
-
84
- it "alias RestClient::Request::RequestFailed to RestClient::RequestFailed" do
85
- RestClient::Request::RequestFailed.should == RestClient::RequestFailed
86
- end
87
-
88
- it "make the exception's response act like an Net::HTTPResponse" do
89
- body = "body"
90
- stub_request(:get, "www.example.com").to_return(:body => body, :status => 404)
91
- begin
92
- RestClient.get "www.example.com"
93
- raise
94
- rescue RestClient::ResourceNotFound => e
95
- e.response.body.should == body
96
- end
97
- end
98
- end