rest-client 1.6.14 → 2.0.2

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.
Files changed (65) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +6 -6
  3. data/.rspec +2 -1
  4. data/.rubocop-disables.yml +384 -0
  5. data/.rubocop.yml +3 -0
  6. data/.travis.yml +46 -1
  7. data/AUTHORS +28 -5
  8. data/Gemfile +5 -1
  9. data/LICENSE +21 -0
  10. data/README.md +784 -0
  11. data/Rakefile +95 -12
  12. data/bin/restclient +11 -12
  13. data/history.md +180 -16
  14. data/lib/restclient.rb +25 -11
  15. data/lib/restclient/abstract_response.rb +171 -51
  16. data/lib/restclient/exceptions.rb +102 -56
  17. data/lib/restclient/params_array.rb +72 -0
  18. data/lib/restclient/payload.rb +43 -74
  19. data/lib/restclient/platform.rb +22 -2
  20. data/lib/restclient/raw_response.rb +7 -3
  21. data/lib/restclient/request.rb +672 -179
  22. data/lib/restclient/resource.rb +6 -7
  23. data/lib/restclient/response.rb +64 -10
  24. data/lib/restclient/utils.rb +235 -0
  25. data/lib/restclient/version.rb +2 -1
  26. data/lib/restclient/windows.rb +8 -0
  27. data/lib/restclient/windows/root_certs.rb +105 -0
  28. data/rest-client.gemspec +16 -11
  29. data/rest-client.windows.gemspec +19 -0
  30. data/spec/helpers.rb +22 -0
  31. data/spec/integration/_lib.rb +1 -0
  32. data/spec/integration/capath_verisign/415660c1.0 +14 -0
  33. data/spec/integration/capath_verisign/7651b327.0 +14 -0
  34. data/spec/integration/capath_verisign/README +8 -0
  35. data/spec/integration/capath_verisign/verisign.crt +14 -0
  36. data/spec/integration/httpbin_spec.rb +87 -0
  37. data/spec/integration/integration_spec.rb +125 -0
  38. data/spec/integration/request_spec.rb +72 -20
  39. data/spec/spec_helper.rb +29 -0
  40. data/spec/unit/_lib.rb +1 -0
  41. data/spec/unit/abstract_response_spec.rb +145 -0
  42. data/spec/unit/exceptions_spec.rb +108 -0
  43. data/spec/{master_shake.jpg → unit/master_shake.jpg} +0 -0
  44. data/spec/unit/params_array_spec.rb +36 -0
  45. data/spec/{payload_spec.rb → unit/payload_spec.rb} +73 -54
  46. data/spec/{raw_response_spec.rb → unit/raw_response_spec.rb} +5 -4
  47. data/spec/unit/request2_spec.rb +54 -0
  48. data/spec/unit/request_spec.rb +1250 -0
  49. data/spec/unit/resource_spec.rb +134 -0
  50. data/spec/unit/response_spec.rb +241 -0
  51. data/spec/unit/restclient_spec.rb +79 -0
  52. data/spec/unit/utils_spec.rb +147 -0
  53. data/spec/unit/windows/root_certs_spec.rb +22 -0
  54. metadata +143 -53
  55. data/README.rdoc +0 -300
  56. data/lib/restclient/net_http_ext.rb +0 -55
  57. data/spec/abstract_response_spec.rb +0 -85
  58. data/spec/base.rb +0 -13
  59. data/spec/exceptions_spec.rb +0 -98
  60. data/spec/integration_spec.rb +0 -38
  61. data/spec/request2_spec.rb +0 -35
  62. data/spec/request_spec.rb +0 -528
  63. data/spec/resource_spec.rb +0 -136
  64. data/spec/response_spec.rb +0 -169
  65. data/spec/restclient_spec.rb +0 -73
data/AUTHORS CHANGED
@@ -3,6 +3,8 @@ the following kind souls:
3
3
 
4
4
  Adam Jacob
5
5
  Adam Wiggins
6
+ Adrian Rangel
7
+ Alex Tomlins
6
8
  Aman Gupta
7
9
  Andy Brody
8
10
  Blake Mizerany
@@ -11,16 +13,21 @@ Braintree
11
13
  Brian Donovan
12
14
  Caleb Land
13
15
  Chris Dinn
16
+ Chris Frohoff
14
17
  Chris Green
15
18
  Coda Hale
16
19
  Crawford
17
20
  Cyril Rohr
18
21
  Dan Mayer
22
+ Dario Hamidi
23
+ Darren Coxall
19
24
  David Backeus
25
+ David Perkowski
20
26
  Dmitri Dolguikh
21
27
  Dusty Doris
22
28
  Dylan Egan
23
29
  El Draper
30
+ Evan Broder
24
31
  Evan Smith
25
32
  François Beausoleil
26
33
  Gabriele Cirulli
@@ -32,16 +39,22 @@ Hiro Asari
32
39
  Hugh McGowan
33
40
  Ian Warshak
34
41
  Ivan Makfinsky
42
+ JH. Chabran
35
43
  James Edward Gray II
36
44
  Jari Bakken
37
45
  Jeff Remer
38
- JH. Chabran
46
+ Jeffrey Hardy
47
+ Jeremy Kemper
48
+ Joe Rafaniello
39
49
  John Barnette
40
50
  Jon Rowe
41
51
  Jordi Massaguer Pla
52
+ Joshua J. Campoverde
42
53
  Juan Alvarez
43
54
  Julien Kirch
55
+ Jun Aruga
44
56
  Justin Coyne
57
+ Justin Lambert
45
58
  Keith Rarick
46
59
  Kenichi Kamiya
47
60
  Kevin Read
@@ -51,25 +64,35 @@ Lars Gierth
51
64
  Lawrence Leonard Gilbert
52
65
  Lee Jarvis
53
66
  Lennon Day-Reynolds
54
- macournoyer
67
+ Lin Jen-Shin
68
+ Marc-André Cournoyer
69
+ Marius Butuc
55
70
  Matthew Manning
56
71
  Michael Klett
72
+ Michael Rykov
73
+ Michael Westbom
57
74
  Mike Fletcher
75
+ Nelson Elhage
58
76
  Nicholas Wieland
77
+ Nick Hammond
59
78
  Nick Plante
60
79
  Niko Dittmann
61
80
  Oscar Del Ben
62
81
  Pablo Astigarraga
63
82
  Paul Dlug
64
83
  Pedro Belo
65
- rafael.ssouza
84
+ Pedro Chambino
66
85
  Philip Corliss
67
- Rick "technoweenie"
86
+ Pierre-Louis Gottfrois
87
+ Rafael Ssouza
88
+ Rick Olson
68
89
  Robert Eanes
69
90
  Rodrigo Panachi
91
+ Samuel Cochran
70
92
  Syl Turner
71
93
  T. Watanabe
72
94
  Tekin
73
- tpresa
74
95
  W. Andrew Loe III
75
96
  Waynn Lue
97
+ Xavier Shay
98
+ tpresa
data/Gemfile CHANGED
@@ -1,6 +1,10 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gemspec
3
+ if !!File::ALT_SEPARATOR
4
+ gemspec :name => 'rest-client.windows'
5
+ else
6
+ gemspec :name => 'rest-client'
7
+ end
4
8
 
5
9
  group :test do
6
10
  gem 'rake'
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2008-2014 Rest Client Authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,784 @@
1
+ # REST Client -- simple DSL for accessing HTTP and REST resources
2
+
3
+ [![Gem Downloads](https://img.shields.io/gem/dt/rest-client.svg)](https://rubygems.org/gems/rest-client)
4
+ [![Build Status](https://travis-ci.org/rest-client/rest-client.svg?branch=master)](https://travis-ci.org/rest-client/rest-client)
5
+ [![Code Climate](https://codeclimate.com/github/rest-client/rest-client.svg)](https://codeclimate.com/github/rest-client/rest-client)
6
+ [![Inline docs](http://inch-ci.org/github/rest-client/rest-client.svg?branch=master)](http://www.rubydoc.info/github/rest-client/rest-client/master)
7
+
8
+ A simple HTTP and REST client for Ruby, inspired by the Sinatra's microframework style
9
+ of specifying actions: get, put, post, delete.
10
+
11
+ * Main page: https://github.com/rest-client/rest-client
12
+ * Mailing list: https://groups.io/g/rest-client
13
+
14
+ ### New mailing list
15
+
16
+ We have a new email list for announcements, hosted by Groups.io.
17
+
18
+ * Subscribe on the web: https://groups.io/g/rest-client
19
+
20
+ * Subscribe by sending an email: mailto:rest-client+subscribe@groups.io
21
+
22
+ * Open discussion subgroup: https://groups.io/g/rest-client+discuss
23
+
24
+ The old Librelist mailing list is *defunct*, as Librelist appears to be broken
25
+ and not accepting new mail. The old archives are still up, but have been
26
+ imported into the new list archives as well.
27
+ http://librelist.com/browser/rest.client
28
+
29
+ ## Requirements
30
+
31
+ MRI Ruby 2.0 and newer are supported. Alternative interpreters compatible with
32
+ 2.0+ should work as well.
33
+
34
+ Earlier Ruby versions such as 1.8.7, 1.9.2, and 1.9.3 are no longer supported. These
35
+ versions no longer have any official support, and do not receive security
36
+ updates.
37
+
38
+ The rest-client gem depends on these other gems for usage at runtime:
39
+
40
+ * [mime-types](http://rubygems.org/gems/mime-types)
41
+ * [netrc](http://rubygems.org/gems/netrc)
42
+ * [http-cookie](https://rubygems.org/gems/http-cookie)
43
+
44
+ There are also several development dependencies. It's recommended to use
45
+ [bundler](http://bundler.io/) to manage these dependencies for hacking on
46
+ rest-client.
47
+
48
+ ### Upgrading to rest-client 2.0 from 1.x
49
+
50
+ Users are encouraged to upgrade to rest-client 2.0, which cleans up a number of
51
+ API warts and wrinkles, making rest-client generally more useful. Usage is
52
+ largely compatible, so many applications will be able to upgrade with no
53
+ changes.
54
+
55
+ Overview of significant changes:
56
+
57
+ * requires Ruby >= 2.0
58
+ * `RestClient::Response` objects are a subclass of `String` rather than a
59
+ Frankenstein monster. And `#body` or `#to_s` return a true `String` object.
60
+ * cleanup of exception classes, including new `RestClient::Exceptions::Timeout`
61
+ * improvements to handling of redirects: responses and history are properly
62
+ exposed
63
+ * major changes to cookie support: cookie jars are used for browser-like
64
+ behavior throughout
65
+ * encoding: Content-Type charset response headers are used to automatically set
66
+ the encoding of the response string
67
+ * HTTP params: handling of GET/POST params is more consistent and sophisticated
68
+ for deeply nested hash objects, and `ParamsArray` can be used to pass ordered
69
+ params
70
+ * improved proxy support with per-request proxy configuration, plus the ability
71
+ to disable proxies set by environment variables
72
+ * default request headers: rest-client sets `Accept: */*` and
73
+ `User-Agent: rest-client/...`
74
+
75
+ See [history.md](./history.md) for a more complete description of changes.
76
+
77
+ ## Usage: Raw URL
78
+
79
+ Basic usage:
80
+
81
+ ```ruby
82
+ require 'rest-client'
83
+
84
+ RestClient.get(url, headers={})
85
+
86
+ RestClient.post(url, payload, headers={})
87
+ ```
88
+
89
+ In the high level helpers, only POST, PATCH, and PUT take a payload argument.
90
+ To pass a payload with other HTTP verbs or to pass more advanced options, use
91
+ `RestClient::Request.execute` instead.
92
+
93
+ More detailed examples:
94
+
95
+ ```ruby
96
+ require 'rest-client'
97
+
98
+ RestClient.get 'http://example.com/resource'
99
+
100
+ RestClient.get 'http://example.com/resource', {params: {id: 50, 'foo' => 'bar'}}
101
+
102
+ RestClient.get 'https://user:password@example.com/private/resource', {accept: :json}
103
+
104
+ RestClient.post 'http://example.com/resource', {param1: 'one', nested: {param2: 'two'}}
105
+
106
+ RestClient.post "http://example.com/resource", {'x' => 1}.to_json, {content_type: :json, accept: :json}
107
+
108
+ RestClient.delete 'http://example.com/resource'
109
+
110
+ >> response = RestClient.get 'http://example.com/resource'
111
+ => <RestClient::Response 200 "<!doctype h...">
112
+ >> response.code
113
+ => 200
114
+ >> response.cookies
115
+ => {"Foo"=>"BAR", "QUUX"=>"QUUUUX"}
116
+ >> response.headers
117
+ => {:content_type=>"text/html; charset=utf-8", :cache_control=>"private" ... }
118
+ >> response.body
119
+ => "<!doctype html>\n<html>\n<head>\n <title>Example Domain</title>\n\n ..."
120
+
121
+ RestClient.post( url,
122
+ {
123
+ :transfer => {
124
+ :path => '/foo/bar',
125
+ :owner => 'that_guy',
126
+ :group => 'those_guys'
127
+ },
128
+ :upload => {
129
+ :file => File.new(path, 'rb')
130
+ }
131
+ })
132
+ ```
133
+ ## Passing advanced options
134
+
135
+ The top level helper methods like RestClient.get accept a headers hash as
136
+ their last argument and don't allow passing more complex options. But these
137
+ helpers are just thin wrappers around `RestClient::Request.execute`.
138
+
139
+ ```ruby
140
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
141
+ timeout: 10)
142
+
143
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
144
+ ssl_ca_file: 'myca.pem',
145
+ ssl_ciphers: 'AESGCM:!aNULL')
146
+ ```
147
+ You can also use this to pass a payload for HTTP verbs like DELETE, where the
148
+ `RestClient.delete` helper doesn't accept a payload.
149
+
150
+ ```ruby
151
+ RestClient::Request.execute(method: :delete, url: 'http://example.com/resource',
152
+ payload: 'foo', headers: {myheader: 'bar'})
153
+ ```
154
+
155
+ Due to unfortunate choices in the original API, the params used to populate the
156
+ query string are actually taken out of the headers hash. So if you want to pass
157
+ both the params hash and more complex options, use the special key
158
+ `:params` in the headers hash. This design may change in a future major
159
+ release.
160
+
161
+ ```ruby
162
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
163
+ timeout: 10, headers: {params: {foo: 'bar'}})
164
+
165
+ ➔ GET http://example.com/resource?foo=bar
166
+ ```
167
+
168
+ ## Multipart
169
+
170
+ Yeah, that's right! This does multipart sends for you!
171
+
172
+ ```ruby
173
+ RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb')
174
+ ```
175
+
176
+ This does two things for you:
177
+
178
+ - Auto-detects that you have a File value sends it as multipart
179
+ - Auto-detects the mime of the file and sets it in the HEAD of the payload for each entry
180
+
181
+ If you are sending params that do not contain a File object but the payload needs to be multipart then:
182
+
183
+ ```ruby
184
+ RestClient.post '/data', {:foo => 'bar', :multipart => true}
185
+ ```
186
+
187
+ ## Usage: ActiveResource-Style
188
+
189
+ ```ruby
190
+ resource = RestClient::Resource.new 'http://example.com/resource'
191
+ resource.get
192
+
193
+ private_resource = RestClient::Resource.new 'https://example.com/private/resource', 'user', 'pass'
194
+ private_resource.put File.read('pic.jpg'), :content_type => 'image/jpg'
195
+ ```
196
+
197
+ See RestClient::Resource module docs for details.
198
+
199
+ ## Usage: Resource Nesting
200
+
201
+ ```ruby
202
+ site = RestClient::Resource.new('http://example.com')
203
+ site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
204
+ ```
205
+ See `RestClient::Resource` docs for details.
206
+
207
+ ## Exceptions (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
208
+
209
+ - for result codes between `200` and `207`, a `RestClient::Response` will be returned
210
+ - for result codes `301`, `302` or `307`, the redirection will be followed if the request is a `GET` or a `HEAD`
211
+ - for result code `303`, the redirection will be followed and the request transformed into a `GET`
212
+ - for other cases, a `RestClient::ExceptionWithResponse` holding the Response will be raised; a specific exception class will be thrown for known error codes
213
+ - call `.response` on the exception to get the server's response
214
+
215
+ ```ruby
216
+ >> RestClient.get 'http://example.com/nonexistent'
217
+ Exception: RestClient::NotFound: 404 Not Found
218
+
219
+ >> begin
220
+ RestClient.get 'http://example.com/nonexistent'
221
+ rescue RestClient::ExceptionWithResponse => e
222
+ e.response
223
+ end
224
+ => <RestClient::Response 404 "<!doctype h...">
225
+ ```
226
+
227
+ ### Other exceptions
228
+
229
+ While most exceptions have been collected under `RestClient::RequestFailed` aka
230
+ `RestClient::ExceptionWithResponse`, there are a few quirky exceptions that
231
+ have been kept for backwards compatibility.
232
+
233
+ RestClient will propagate up exceptions like socket errors without modification:
234
+
235
+ ```ruby
236
+ >> RestClient.get 'http://localhost:12345'
237
+ Exception: Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 12345
238
+ ```
239
+
240
+ RestClient handles a few specific error cases separately in order to give
241
+ better error messages. These will hopefully be cleaned up in a future major
242
+ release.
243
+
244
+ `RestClient::ServerBrokeConnection` is translated from `EOFError` to give a
245
+ better error message.
246
+
247
+ `RestClient::SSLCertificateNotVerified` is raised when HTTPS validation fails.
248
+ Other `OpenSSL::SSL::SSLError` errors are raised as is.
249
+
250
+ ### Redirection
251
+
252
+ By default, rest-client will follow HTTP 30x redirection requests.
253
+
254
+ __New in 2.0:__ `RestClient::Response` exposes a `#history` method that returns
255
+ a list of each response received in a redirection chain.
256
+
257
+ ```ruby
258
+ >> r = RestClient.get('http://httpbin.org/redirect/2')
259
+ => <RestClient::Response 200 "{\n \"args\":...">
260
+
261
+ # see each response in the redirect chain
262
+ >> r.history
263
+ => [<RestClient::Response 302 "<!DOCTYPE H...">, <RestClient::Response 302 "">]
264
+
265
+ # see each requested URL
266
+ >> r.request.url
267
+ => "http://httpbin.org/get"
268
+ >> r.history.map {|x| x.request.url}
269
+ => ["http://httpbin.org/redirect/2", "http://httpbin.org/relative-redirect/1"]
270
+ ```
271
+
272
+ #### Manually following redirection
273
+
274
+ To disable automatic redirection, set `:max_redirects => 0`.
275
+
276
+ __New in 2.0:__ Prior versions of rest-client would raise
277
+ `RestClient::MaxRedirectsReached`, with no easy way to access the server's
278
+ response. In 2.0, rest-client raises the normal
279
+ `RestClient::ExceptionWithResponse` as it would with any other non-HTTP-20x
280
+ response.
281
+
282
+ ```ruby
283
+ >> RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/1')
284
+ => RestClient::Response 200 "{\n "args":..."
285
+
286
+ >> RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/1', max_redirects: 0)
287
+ RestClient::Found: 302 Found
288
+ ```
289
+
290
+ To manually follow redirection, you can call `Response#follow_redirection`. Or
291
+ you could of course inspect the result and choose custom behavior.
292
+
293
+ ```ruby
294
+ >> RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/1', max_redirects: 0)
295
+ RestClient::Found: 302 Found
296
+ >> begin
297
+ RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/1', max_redirects: 0)
298
+ rescue RestClient::ExceptionWithResponse => err
299
+ end
300
+ >> err
301
+ => #<RestClient::Found: 302 Found>
302
+ >> err.response
303
+ => RestClient::Response 302 "<!DOCTYPE H..."
304
+ >> err.response.headers[:location]
305
+ => "/get"
306
+ >> err.response.follow_redirection
307
+ => RestClient::Response 200 "{\n "args":..."
308
+ ```
309
+
310
+ ## Result handling
311
+
312
+ The result of a `RestClient::Request` is a `RestClient::Response` object.
313
+
314
+ __New in 2.0:__ `RestClient::Response` objects are now a subclass of `String`.
315
+ Previously, they were a real String object with response functionality mixed
316
+ in, which was very confusing to work with.
317
+
318
+ Response objects have several useful methods. (See the class rdoc for more details.)
319
+
320
+ - `Response#code`: The HTTP response code
321
+ - `Response#body`: The response body as a string. (AKA .to_s)
322
+ - `Response#headers`: A hash of HTTP response headers
323
+ - `Response#raw_headers`: A hash of HTTP response headers as unprocessed arrays
324
+ - `Response#cookies`: A hash of HTTP cookies set by the server
325
+ - `Response#cookie_jar`: <em>New in 1.8</em> An HTTP::CookieJar of cookies
326
+ - `Response#request`: The RestClient::Request object used to make the request
327
+ - `Response#history`: <em>New in 2.0</em> If redirection was followed, a list of prior Response objects
328
+
329
+ ```ruby
330
+ RestClient.get('http://example.com')
331
+ ➔ <RestClient::Response 200 "<!doctype h...">
332
+
333
+ begin
334
+ RestClient.get('http://example.com/notfound')
335
+ rescue RestClient::ExceptionWithResponse => err
336
+ err.response
337
+ end
338
+ ➔ <RestClient::Response 404 "<!doctype h...">
339
+ ```
340
+
341
+ ### Response callbacks, error handling
342
+
343
+ A block can be passed to the RestClient method. This block will then be called with the Response.
344
+ Response.return! can be called to invoke the default response's behavior.
345
+
346
+ ```ruby
347
+ # Don't raise exceptions but return the response
348
+ >> RestClient.get('http://example.com/nonexistent') {|response, request, result| response }
349
+ => <RestClient::Response 404 "<!doctype h...">
350
+ ```
351
+
352
+ ```ruby
353
+ # Manage a specific error code
354
+ RestClient.get('http://example.com/resource') { |response, request, result, &block|
355
+ case response.code
356
+ when 200
357
+ p "It worked !"
358
+ response
359
+ when 423
360
+ raise SomeCustomExceptionIfYouWant
361
+ else
362
+ response.return!(request, result, &block)
363
+ end
364
+ }
365
+ ```
366
+
367
+ But note that it may be more straightforward to use exceptions to handle
368
+ different HTTP error response cases:
369
+
370
+ ```ruby
371
+ begin
372
+ resp = RestClient.get('http://example.com/resource')
373
+ rescue RestClient::Unauthorized, RestClient::Forbidden => err
374
+ puts 'Access denied'
375
+ return err.response
376
+ rescue RestClient::ImATeapot => err
377
+ puts 'The server is a teapot! # RFC 2324'
378
+ return err.response
379
+ else
380
+ puts 'It worked!'
381
+ return resp
382
+ end
383
+ ```
384
+
385
+ For GET and HEAD requests, rest-client automatically follows redirection. For
386
+ other HTTP verbs, call `.follow_redirection` on the response object (works both
387
+ in block form and in exception form).
388
+
389
+ ```ruby
390
+ # Follow redirections for all request types and not only for get and head
391
+ # RFC : "If the 301, 302 or 307 status code is received in response to a request other than GET or HEAD,
392
+ # the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user,
393
+ # since this might change the conditions under which the request was issued."
394
+
395
+ # block style
396
+ RestClient.post('http://example.com/redirect', 'body') { |response, request, result|
397
+ case response.code
398
+ when 301, 302, 307
399
+ response.follow_redirection
400
+ else
401
+ response.return!
402
+ end
403
+ }
404
+
405
+ # exception style by explicit classes
406
+ begin
407
+ RestClient.post('http://example.com/redirect', 'body')
408
+ rescue RestClient::MovedPermanently,
409
+ RestClient::Found,
410
+ RestClient::TemporaryRedirect => err
411
+ err.response.follow_redirection
412
+ end
413
+
414
+ # exception style by response code
415
+ begin
416
+ RestClient.post('http://example.com/redirect', 'body')
417
+ rescue RestClient::ExceptionWithResponse => err
418
+ case err.http_code
419
+ when 301, 302, 307
420
+ err.response.follow_redirection
421
+ else
422
+ raise
423
+ end
424
+ end
425
+ ```
426
+
427
+ ## Non-normalized URIs
428
+
429
+ If you need to normalize URIs, e.g. to work with International Resource Identifiers (IRIs),
430
+ use the addressable gem (http://addressable.rubyforge.org/api/) in your code:
431
+
432
+ ```ruby
433
+ require 'addressable/uri'
434
+ RestClient.get(Addressable::URI.parse("http://www.詹姆斯.com/").normalize.to_str)
435
+ ```
436
+
437
+ ## Lower-level access
438
+
439
+ For cases not covered by the general API, you can use the `RestClient::Request` class, which provides a lower-level API.
440
+
441
+ You can:
442
+
443
+ - specify ssl parameters
444
+ - override cookies
445
+ - manually handle the response (e.g. to operate on it as a stream rather than reading it all into memory)
446
+
447
+ See `RestClient::Request`'s documentation for more information.
448
+
449
+ ## Shell
450
+
451
+ The restclient shell command gives an IRB session with RestClient already loaded:
452
+
453
+ ```ruby
454
+ $ restclient
455
+ >> RestClient.get 'http://example.com'
456
+ ```
457
+
458
+ Specify a URL argument for get/post/put/delete on that resource:
459
+
460
+ ```ruby
461
+ $ restclient http://example.com
462
+ >> put '/resource', 'data'
463
+ ```
464
+
465
+ Add a user and password for authenticated resources:
466
+
467
+ ```ruby
468
+ $ restclient https://example.com user pass
469
+ >> delete '/private/resource'
470
+ ```
471
+
472
+ Create ~/.restclient for named sessions:
473
+
474
+ ```ruby
475
+ sinatra:
476
+ url: http://localhost:4567
477
+ rack:
478
+ url: http://localhost:9292
479
+ private_site:
480
+ url: http://example.com
481
+ username: user
482
+ password: pass
483
+ ```
484
+
485
+ Then invoke:
486
+
487
+ ```ruby
488
+ $ restclient private_site
489
+ ```
490
+
491
+ Use as a one-off, curl-style:
492
+
493
+ ```ruby
494
+ $ restclient get http://example.com/resource > output_body
495
+
496
+ $ restclient put http://example.com/resource < input_body
497
+ ```
498
+
499
+ ## Logging
500
+
501
+ To enable logging you can:
502
+
503
+ - set RestClient.log with a Ruby Logger, or
504
+ - set an environment variable to avoid modifying the code (in this case you can use a file name, "stdout" or "stderr"):
505
+
506
+ ```ruby
507
+ $ RESTCLIENT_LOG=stdout path/to/my/program
508
+ ```
509
+ Either produces logs like this:
510
+
511
+ ```ruby
512
+ RestClient.get "http://some/resource"
513
+ # => 200 OK | text/html 250 bytes
514
+ RestClient.put "http://some/resource", "payload"
515
+ # => 401 Unauthorized | application/xml 340 bytes
516
+ ```
517
+
518
+ Note that these logs are valid Ruby, so you can paste them into the `restclient`
519
+ shell or a script to replay your sequence of rest calls.
520
+
521
+ ## Proxy
522
+
523
+ All calls to RestClient, including Resources, will use the proxy specified by
524
+ `RestClient.proxy`:
525
+
526
+ ```ruby
527
+ RestClient.proxy = "http://proxy.example.com/"
528
+ RestClient.get "http://some/resource"
529
+ # => response from some/resource as proxied through proxy.example.com
530
+ ```
531
+
532
+ Often the proxy URL is set in an environment variable, so you can do this to
533
+ use whatever proxy the system is configured to use:
534
+
535
+ ```ruby
536
+ RestClient.proxy = ENV['http_proxy']
537
+ ```
538
+
539
+ __New in 2.0:__ Specify a per-request proxy by passing the :proxy option to
540
+ RestClient::Request. This will override any proxies set by environment variable
541
+ or by the global `RestClient.proxy` value.
542
+
543
+ ```ruby
544
+ RestClient::Request.execute(method: :get, url: 'http://example.com',
545
+ proxy: 'http://proxy.example.com')
546
+ # => single request proxied through the proxy
547
+ ```
548
+
549
+ This can be used to disable the use of a proxy for a particular request.
550
+
551
+ ```ruby
552
+ RestClient.proxy = "http://proxy.example.com/"
553
+ RestClient::Request.execute(method: :get, url: 'http://example.com', proxy: nil)
554
+ # => single request sent without a proxy
555
+ ```
556
+
557
+ ## Query parameters
558
+
559
+ Rest-client can render a hash as HTTP query parameters for GET/HEAD/DELETE
560
+ requests or as HTTP post data in `x-www-form-urlencoded` format for POST
561
+ requests.
562
+
563
+ __New in 2.0:__ Even though there is no standard specifying how this should
564
+ work, rest-client follows a similar convention to the one used by Rack / Rails
565
+ servers for handling arrays, nested hashes, and null values.
566
+
567
+ The implementation in
568
+ [./lib/rest-client/utils.rb](RestClient::Utils.encode_query_string)
569
+ closely follows
570
+ [Rack::Utils.build_nested_query](http://www.rubydoc.info/gems/rack/Rack/Utils#build_nested_query-class_method),
571
+ but treats empty arrays and hashes as `nil`. (Rack drops them entirely, which
572
+ is confusing behavior.)
573
+
574
+ If you don't like this behavior and want more control, just serialize params
575
+ yourself (e.g. with `URI.encode_www_form`) and add the query string to the URL
576
+ directly for GET parameters or pass the payload as a string for POST requests.
577
+
578
+ Basic GET params:
579
+ ```ruby
580
+ RestClient.get('https://httpbin.org/get', params: {foo: 'bar', baz: 'qux'})
581
+ # GET "https://httpbin.org/get?foo=bar&baz=qux"
582
+ ```
583
+
584
+ Basic `x-www-form-urlencoded` POST params:
585
+ ```ruby
586
+ >> r = RestClient.post('https://httpbin.org/post', {foo: 'bar', baz: 'qux'})
587
+ # POST "https://httpbin.org/post", data: "foo=bar&baz=qux"
588
+ => <RestClient::Response 200 "{\n \"args\":...">
589
+ >> JSON.parse(r.body)
590
+ => {"args"=>{},
591
+ "data"=>"",
592
+ "files"=>{},
593
+ "form"=>{"baz"=>"qux", "foo"=>"bar"},
594
+ "headers"=>
595
+ {"Accept"=>"*/*",
596
+ "Accept-Encoding"=>"gzip, deflate",
597
+ "Content-Length"=>"15",
598
+ "Content-Type"=>"application/x-www-form-urlencoded",
599
+ "Host"=>"httpbin.org"},
600
+ "json"=>nil,
601
+ "url"=>"https://httpbin.org/post"}
602
+ ```
603
+
604
+ JSON payload: rest-client does not speak JSON natively, so serialize your
605
+ payload to a string before passing it to rest-client.
606
+ ```ruby
607
+ >> payload = {'name' => 'newrepo', 'description': 'A new repo'}
608
+ >> RestClient.post('https://api.github.com/user/repos', payload.to_json, content_type: :json)
609
+ => <RestClient::Response 201 "{\"id\":75149...">
610
+ ```
611
+
612
+ Advanced GET params (arrays):
613
+ ```ruby
614
+ >> r = RestClient.get('https://http-params.herokuapp.com/get', params: {foo: [1,2,3]})
615
+ # GET "https://http-params.herokuapp.com/get?foo[]=1&foo[]=2&foo[]=3"
616
+ => <RestClient::Response 200 "Method: GET...">
617
+ >> puts r.body
618
+ query_string: "foo[]=1&foo[]=2&foo[]=3"
619
+ decoded: "foo[]=1&foo[]=2&foo[]=3"
620
+
621
+ GET:
622
+ {"foo"=>["1", "2", "3"]}
623
+ ```
624
+
625
+ Advanced GET params (nested hashes):
626
+ ```ruby
627
+ >> r = RestClient.get('https://http-params.herokuapp.com/get', params: {outer: {foo: 123, bar: 456}})
628
+ # GET "https://http-params.herokuapp.com/get?outer[foo]=123&outer[bar]=456"
629
+ => <RestClient::Response 200 "Method: GET...">
630
+ >> puts r.body
631
+ ...
632
+ query_string: "outer[foo]=123&outer[bar]=456"
633
+ decoded: "outer[foo]=123&outer[bar]=456"
634
+
635
+ GET:
636
+ {"outer"=>{"foo"=>"123", "bar"=>"456"}}
637
+ ```
638
+
639
+ __New in 2.0:__ The new `RestClient::ParamsArray` class allows callers to
640
+ provide ordering even to structured parameters. This is useful for unusual
641
+ cases where the server treats the order of parameters as significant or you
642
+ want to pass a particular key multiple times.
643
+
644
+ Multiple fields with the same name using ParamsArray:
645
+ ```ruby
646
+ >> RestClient.get('https://httpbin.org/get', params:
647
+ RestClient::ParamsArray.new([[:foo, 1], [:foo, 2]]))
648
+ # GET "https://httpbin.org/get?foo=1&foo=2"
649
+ ```
650
+
651
+ Nested ParamsArray:
652
+ ```ruby
653
+ >> RestClient.get('https://httpbin.org/get', params:
654
+ {foo: RestClient::ParamsArray.new([[:a, 1], [:a, 2]])})
655
+ # GET "https://httpbin.org/get?foo[a]=1&foo[a]=2"
656
+ ```
657
+
658
+ ## Headers
659
+
660
+ Request headers can be set by passing a ruby hash containing keys and values
661
+ representing header names and values:
662
+
663
+ ```ruby
664
+ # GET request with modified headers
665
+ RestClient.get 'http://example.com/resource', {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
666
+
667
+ # POST request with modified headers
668
+ RestClient.post 'http://example.com/resource', {:foo => 'bar', :baz => 'qux'}, {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
669
+
670
+ # DELETE request with modified headers
671
+ RestClient.delete 'http://example.com/resource', {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
672
+ ```
673
+
674
+ ## Timeouts
675
+
676
+ By default the timeout for a request is 60 seconds. Timeouts for your request can
677
+ be adjusted by setting the `timeout:` to the number of seconds that you would like
678
+ the request to wait. Setting `timeout:` will override both `read_timeout:` and `open_timeout:`.
679
+
680
+ ```ruby
681
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
682
+ timeout: 120)
683
+ ```
684
+
685
+ Additionally, you can set `read_timeout:` and `open_timeout:` separately.
686
+
687
+ ```ruby
688
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
689
+ read_timeout: 120, open_timeout: 240)
690
+ ```
691
+
692
+ ## Cookies
693
+
694
+ Request and Response objects know about HTTP cookies, and will automatically
695
+ extract and set headers for them as needed:
696
+
697
+ ```ruby
698
+ response = RestClient.get 'http://example.com/action_which_sets_session_id'
699
+ response.cookies
700
+ # => {"_applicatioN_session_id" => "1234"}
701
+
702
+ response2 = RestClient.post(
703
+ 'http://localhost:3000/',
704
+ {:param1 => "foo"},
705
+ {:cookies => {:session_id => "1234"}}
706
+ )
707
+ # ...response body
708
+ ```
709
+ ### Full cookie jar support (new in 1.8)
710
+
711
+ The original cookie implementation was very naive and ignored most of the
712
+ cookie RFC standards.
713
+ __New in 1.8__: An HTTP::CookieJar of cookies
714
+
715
+ Response objects now carry a cookie_jar method that exposes an HTTP::CookieJar
716
+ of cookies, which supports full standards compliant behavior.
717
+
718
+ ## SSL/TLS support
719
+
720
+ Various options are supported for configuring rest-client's TLS settings. By
721
+ default, rest-client will verify certificates using the system's CA store on
722
+ all platforms. (This is intended to be similar to how browsers behave.) You can
723
+ specify an :ssl_ca_file, :ssl_ca_path, or :ssl_cert_store to customize the
724
+ certificate authorities accepted.
725
+
726
+ ### SSL Client Certificates
727
+
728
+ ```ruby
729
+ RestClient::Resource.new(
730
+ 'https://example.com',
731
+ :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read("cert.pem")),
732
+ :ssl_client_key => OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
733
+ :ssl_ca_file => "ca_certificate.pem",
734
+ :verify_ssl => OpenSSL::SSL::VERIFY_PEER
735
+ ).get
736
+ ```
737
+ Self-signed certificates can be generated with the openssl command-line tool.
738
+
739
+ ## Hook
740
+
741
+ RestClient.add_before_execution_proc add a Proc to be called before each execution.
742
+ It's handy if you need direct access to the HTTP request.
743
+
744
+ Example:
745
+
746
+ ```ruby
747
+ # Add oauth support using the oauth gem
748
+ require 'oauth'
749
+ access_token = ...
750
+
751
+ RestClient.add_before_execution_proc do |req, params|
752
+ access_token.sign! req
753
+ end
754
+
755
+ RestClient.get 'http://example.com'
756
+ ```
757
+
758
+ ## More
759
+
760
+ Need caching, more advanced logging or any ability provided by Rack middleware?
761
+
762
+ Have a look at rest-client-components: http://github.com/crohr/rest-client-components
763
+
764
+ ## Credits
765
+ | | |
766
+ |-------------------------|---------------------------------------------------------|
767
+ | **REST Client Team** | Andy Brody |
768
+ | **Creator** | Adam Wiggins |
769
+ | **Maintainers Emeriti** | Lawrence Leonard Gilbert, Matthew Manning, Julien Kirch |
770
+ | **Major contributions** | Blake Mizerany, Julien Kirch |
771
+
772
+ A great many generous folks have contributed features and patches.
773
+ See AUTHORS for the full list.
774
+
775
+ ## Legal
776
+
777
+ Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
778
+
779
+ "Master Shake" photo (http://www.flickr.com/photos/solgrundy/924205581/) by
780
+ "SolGrundy"; used under terms of the Creative Commons Attribution-ShareAlike 2.0
781
+ Generic license (http://creativecommons.org/licenses/by-sa/2.0/)
782
+
783
+ Code for reading Windows root certificate store derived from work by Puppet;
784
+ used under terms of the Apache License, Version 2.0.