rest-client 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rspec +2 -0
  4. data/.rubocop-disables.yml +384 -0
  5. data/.rubocop.yml +3 -0
  6. data/.travis.yml +48 -0
  7. data/AUTHORS +98 -0
  8. data/Gemfile +11 -0
  9. data/LICENSE +21 -0
  10. data/README.md +784 -0
  11. data/Rakefile +132 -0
  12. data/bin/restclient +92 -0
  13. data/history.md +324 -0
  14. data/lib/rest-client.rb +2 -0
  15. data/lib/rest_client.rb +2 -0
  16. data/lib/restclient.rb +184 -0
  17. data/lib/restclient/abstract_response.rb +226 -0
  18. data/lib/restclient/exceptions.rb +244 -0
  19. data/lib/restclient/params_array.rb +72 -0
  20. data/lib/restclient/payload.rb +209 -0
  21. data/lib/restclient/platform.rb +49 -0
  22. data/lib/restclient/raw_response.rb +38 -0
  23. data/lib/restclient/request.rb +853 -0
  24. data/lib/restclient/resource.rb +168 -0
  25. data/lib/restclient/response.rb +80 -0
  26. data/lib/restclient/utils.rb +235 -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 +31 -0
  31. data/rest-client.windows.gemspec +19 -0
  32. data/spec/helpers.rb +22 -0
  33. data/spec/integration/_lib.rb +1 -0
  34. data/spec/integration/capath_digicert/244b5494.0 +19 -0
  35. data/spec/integration/capath_digicert/81b9768f.0 +19 -0
  36. data/spec/integration/capath_digicert/README +8 -0
  37. data/spec/integration/capath_digicert/digicert.crt +19 -0
  38. data/spec/integration/capath_verisign/415660c1.0 +14 -0
  39. data/spec/integration/capath_verisign/7651b327.0 +14 -0
  40. data/spec/integration/capath_verisign/README +8 -0
  41. data/spec/integration/capath_verisign/verisign.crt +14 -0
  42. data/spec/integration/certs/digicert.crt +19 -0
  43. data/spec/integration/certs/verisign.crt +14 -0
  44. data/spec/integration/httpbin_spec.rb +87 -0
  45. data/spec/integration/integration_spec.rb +125 -0
  46. data/spec/integration/request_spec.rb +127 -0
  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/master_shake.jpg +0 -0
  52. data/spec/unit/params_array_spec.rb +36 -0
  53. data/spec/unit/payload_spec.rb +263 -0
  54. data/spec/unit/raw_response_spec.rb +18 -0
  55. data/spec/unit/request2_spec.rb +54 -0
  56. data/spec/unit/request_spec.rb +1250 -0
  57. data/spec/unit/resource_spec.rb +134 -0
  58. data/spec/unit/response_spec.rb +241 -0
  59. data/spec/unit/restclient_spec.rb +79 -0
  60. data/spec/unit/utils_spec.rb +147 -0
  61. data/spec/unit/windows/root_certs_spec.rb +22 -0
  62. metadata +282 -0
data/AUTHORS ADDED
@@ -0,0 +1,98 @@
1
+ The Ruby REST Client would not be what it is today without the help of
2
+ the following kind souls:
3
+
4
+ Adam Jacob
5
+ Adam Wiggins
6
+ Adrian Rangel
7
+ Alex Tomlins
8
+ Aman Gupta
9
+ Andy Brody
10
+ Blake Mizerany
11
+ Brad Ediger
12
+ Braintree
13
+ Brian Donovan
14
+ Caleb Land
15
+ Chris Dinn
16
+ Chris Frohoff
17
+ Chris Green
18
+ Coda Hale
19
+ Crawford
20
+ Cyril Rohr
21
+ Dan Mayer
22
+ Dario Hamidi
23
+ Darren Coxall
24
+ David Backeus
25
+ David Perkowski
26
+ Dmitri Dolguikh
27
+ Dusty Doris
28
+ Dylan Egan
29
+ El Draper
30
+ Evan Broder
31
+ Evan Smith
32
+ François Beausoleil
33
+ Gabriele Cirulli
34
+ Garry Shutler
35
+ Giovanni Cappellotto
36
+ Greg Borenstein
37
+ Harm Aarts
38
+ Hiro Asari
39
+ Hugh McGowan
40
+ Ian Warshak
41
+ Ivan Makfinsky
42
+ JH. Chabran
43
+ James Edward Gray II
44
+ Jari Bakken
45
+ Jeff Remer
46
+ Jeffrey Hardy
47
+ Jeremy Kemper
48
+ Joe Rafaniello
49
+ John Barnette
50
+ Jon Rowe
51
+ Jordi Massaguer Pla
52
+ Joshua J. Campoverde
53
+ Juan Alvarez
54
+ Julien Kirch
55
+ Jun Aruga
56
+ Justin Coyne
57
+ Justin Lambert
58
+ Keith Rarick
59
+ Kenichi Kamiya
60
+ Kevin Read
61
+ Kosuke Asami
62
+ Kyle VanderBeek
63
+ Lars Gierth
64
+ Lawrence Leonard Gilbert
65
+ Lee Jarvis
66
+ Lennon Day-Reynolds
67
+ Lin Jen-Shin
68
+ Marc-André Cournoyer
69
+ Marius Butuc
70
+ Matthew Manning
71
+ Michael Klett
72
+ Michael Rykov
73
+ Michael Westbom
74
+ Mike Fletcher
75
+ Nelson Elhage
76
+ Nicholas Wieland
77
+ Nick Hammond
78
+ Nick Plante
79
+ Niko Dittmann
80
+ Oscar Del Ben
81
+ Pablo Astigarraga
82
+ Paul Dlug
83
+ Pedro Belo
84
+ Pedro Chambino
85
+ Philip Corliss
86
+ Pierre-Louis Gottfrois
87
+ Rafael Ssouza
88
+ Rick Olson
89
+ Robert Eanes
90
+ Rodrigo Panachi
91
+ Samuel Cochran
92
+ Syl Turner
93
+ T. Watanabe
94
+ Tekin
95
+ W. Andrew Loe III
96
+ Waynn Lue
97
+ Xavier Shay
98
+ tpresa
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ if !!File::ALT_SEPARATOR
4
+ gemspec :name => 'rest-client.windows'
5
+ else
6
+ gemspec :name => 'rest-client'
7
+ end
8
+
9
+ group :test do
10
+ gem 'rake'
11
+ end
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.