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/AUTHORS ADDED
@@ -0,0 +1,106 @@
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
+ Avi Deitcher
11
+ Blake Mizerany
12
+ Brad Ediger
13
+ Braintree
14
+ Brian Donovan
15
+ Caleb Land
16
+ Chris Dinn
17
+ Chris Frohoff
18
+ Chris Green
19
+ Coda Hale
20
+ Crawford
21
+ Cyril Rohr
22
+ Dan Mayer
23
+ Dario Hamidi
24
+ Darren Coxall
25
+ David Backeus
26
+ David Perkowski
27
+ Dmitri Dolguikh
28
+ Dusty Doris
29
+ Dylan Egan
30
+ El Draper
31
+ Evan Broder
32
+ Evan Smith
33
+ François Beausoleil
34
+ Gabriele Cirulli
35
+ Garry Shutler
36
+ Giovanni Cappellotto
37
+ Greg Borenstein
38
+ Harm Aarts
39
+ Hiro Asari
40
+ Hugh McGowan
41
+ Ian Warshak
42
+ Igor Zubkov
43
+ Ivan Makfinsky
44
+ JH. Chabran
45
+ James Edward Gray II
46
+ Jari Bakken
47
+ Jeff Pereira
48
+ Jeff Remer
49
+ Jeffrey Hardy
50
+ Jeremy Kemper
51
+ Joe Rafaniello
52
+ John Barnette
53
+ Jon Rowe
54
+ Jordi Massaguer Pla
55
+ Joshua J. Campoverde
56
+ Juan Alvarez
57
+ Julien Kirch
58
+ Jun Aruga
59
+ Justin Coyne
60
+ Justin Lambert
61
+ Keith Rarick
62
+ Kenichi Kamiya
63
+ Kevin Read
64
+ Kosuke Asami
65
+ Kyle Meyer
66
+ Kyle VanderBeek
67
+ Lars Gierth
68
+ Lawrence Leonard Gilbert
69
+ Lee Jarvis
70
+ Lennon Day-Reynolds
71
+ Lin Jen-Shin
72
+ Magne Matre Gåsland
73
+ Marc-André Cournoyer
74
+ Marius Butuc
75
+ Matthew Manning
76
+ Michael Klett
77
+ Michael Rykov
78
+ Michael Westbom
79
+ Mike Fletcher
80
+ Nelson Elhage
81
+ Nicholas Wieland
82
+ Nick Hammond
83
+ Nick Plante
84
+ Niko Dittmann
85
+ Nikolay Shebanov
86
+ Oscar Del Ben
87
+ Pablo Astigarraga
88
+ Paul Dlug
89
+ Pedro Belo
90
+ Pedro Chambino
91
+ Philip Corliss
92
+ Pierre-Louis Gottfrois
93
+ Rafael Ssouza
94
+ Richard Schneeman
95
+ Rick Olson
96
+ Robert Eanes
97
+ Rodrigo Panachi
98
+ Sam Norbury
99
+ Samuel Cochran
100
+ Syl Turner
101
+ T. Watanabe
102
+ Tekin
103
+ W. Andrew Loe III
104
+ Waynn Lue
105
+ Xavier Shay
106
+ 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.
data/README.md ADDED
@@ -0,0 +1,901 @@
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-accept](https://rubygems.org/gems/http-accept)
43
+ * [http-cookie](https://rubygems.org/gems/http-cookie)
44
+
45
+ There are also several development dependencies. It's recommended to use
46
+ [bundler](http://bundler.io/) to manage these dependencies for hacking on
47
+ rest-client.
48
+
49
+ ### Upgrading to rest-client 2.0 from 1.x
50
+
51
+ Users are encouraged to upgrade to rest-client 2.0, which cleans up a number of
52
+ API warts and wrinkles, making rest-client generally more useful. Usage is
53
+ largely compatible, so many applications will be able to upgrade with no
54
+ changes.
55
+
56
+ Overview of significant changes:
57
+
58
+ * requires Ruby >= 2.0
59
+ * `RestClient::Response` objects are a subclass of `String` rather than a
60
+ Frankenstein monster. And `#body` or `#to_s` return a true `String` object.
61
+ * cleanup of exception classes, including new `RestClient::Exceptions::Timeout`
62
+ * improvements to handling of redirects: responses and history are properly
63
+ exposed
64
+ * major changes to cookie support: cookie jars are used for browser-like
65
+ behavior throughout
66
+ * encoding: Content-Type charset response headers are used to automatically set
67
+ the encoding of the response string
68
+ * HTTP params: handling of GET/POST params is more consistent and sophisticated
69
+ for deeply nested hash objects, and `ParamsArray` can be used to pass ordered
70
+ params
71
+ * improved proxy support with per-request proxy configuration, plus the ability
72
+ to disable proxies set by environment variables
73
+ * default request headers: rest-client sets `Accept: */*` and
74
+ `User-Agent: rest-client/...`
75
+
76
+ See [history.md](./history.md) for a more complete description of changes.
77
+
78
+ ## Usage: Raw URL
79
+
80
+ Basic usage:
81
+
82
+ ```ruby
83
+ require 'rest-client'
84
+
85
+ RestClient.get(url, headers={})
86
+
87
+ RestClient.post(url, payload, headers={})
88
+ ```
89
+
90
+ In the high level helpers, only POST, PATCH, and PUT take a payload argument.
91
+ To pass a payload with other HTTP verbs or to pass more advanced options, use
92
+ `RestClient::Request.execute` instead.
93
+
94
+ More detailed examples:
95
+
96
+ ```ruby
97
+ require 'rest-client'
98
+
99
+ RestClient.get 'http://example.com/resource'
100
+
101
+ RestClient.get 'http://example.com/resource', {params: {id: 50, 'foo' => 'bar'}}
102
+
103
+ RestClient.get 'https://user:password@example.com/private/resource', {accept: :json}
104
+
105
+ RestClient.post 'http://example.com/resource', {param1: 'one', nested: {param2: 'two'}}
106
+
107
+ RestClient.post "http://example.com/resource", {'x' => 1}.to_json, {content_type: :json, accept: :json}
108
+
109
+ RestClient.delete 'http://example.com/resource'
110
+
111
+ >> response = RestClient.get 'http://example.com/resource'
112
+ => <RestClient::Response 200 "<!doctype h...">
113
+ >> response.code
114
+ => 200
115
+ >> response.cookies
116
+ => {"Foo"=>"BAR", "QUUX"=>"QUUUUX"}
117
+ >> response.headers
118
+ => {:content_type=>"text/html; charset=utf-8", :cache_control=>"private" ... }
119
+ >> response.body
120
+ => "<!doctype html>\n<html>\n<head>\n <title>Example Domain</title>\n\n ..."
121
+
122
+ RestClient.post( url,
123
+ {
124
+ :transfer => {
125
+ :path => '/foo/bar',
126
+ :owner => 'that_guy',
127
+ :group => 'those_guys'
128
+ },
129
+ :upload => {
130
+ :file => File.new(path, 'rb')
131
+ }
132
+ })
133
+ ```
134
+ ## Passing advanced options
135
+
136
+ The top level helper methods like RestClient.get accept a headers hash as
137
+ their last argument and don't allow passing more complex options. But these
138
+ helpers are just thin wrappers around `RestClient::Request.execute`.
139
+
140
+ ```ruby
141
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
142
+ timeout: 10)
143
+
144
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
145
+ ssl_ca_file: 'myca.pem',
146
+ ssl_ciphers: 'AESGCM:!aNULL')
147
+ ```
148
+ You can also use this to pass a payload for HTTP verbs like DELETE, where the
149
+ `RestClient.delete` helper doesn't accept a payload.
150
+
151
+ ```ruby
152
+ RestClient::Request.execute(method: :delete, url: 'http://example.com/resource',
153
+ payload: 'foo', headers: {myheader: 'bar'})
154
+ ```
155
+
156
+ Due to unfortunate choices in the original API, the params used to populate the
157
+ query string are actually taken out of the headers hash. So if you want to pass
158
+ both the params hash and more complex options, use the special key
159
+ `:params` in the headers hash. This design may change in a future major
160
+ release.
161
+
162
+ ```ruby
163
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
164
+ timeout: 10, headers: {params: {foo: 'bar'}})
165
+
166
+ ➔ GET http://example.com/resource?foo=bar
167
+ ```
168
+
169
+ ## Multipart
170
+
171
+ Yeah, that's right! This does multipart sends for you!
172
+
173
+ ```ruby
174
+ RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb')
175
+ ```
176
+
177
+ This does two things for you:
178
+
179
+ - Auto-detects that you have a File value sends it as multipart
180
+ - Auto-detects the mime of the file and sets it in the HEAD of the payload for each entry
181
+
182
+ If you are sending params that do not contain a File object but the payload needs to be multipart then:
183
+
184
+ ```ruby
185
+ RestClient.post '/data', {:foo => 'bar', :multipart => true}
186
+ ```
187
+
188
+ ## Usage: ActiveResource-Style
189
+
190
+ ```ruby
191
+ resource = RestClient::Resource.new 'http://example.com/resource'
192
+ resource.get
193
+
194
+ private_resource = RestClient::Resource.new 'https://example.com/private/resource', 'user', 'pass'
195
+ private_resource.put File.read('pic.jpg'), :content_type => 'image/jpg'
196
+ ```
197
+
198
+ See RestClient::Resource module docs for details.
199
+
200
+ ## Usage: Resource Nesting
201
+
202
+ ```ruby
203
+ site = RestClient::Resource.new('http://example.com')
204
+ site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
205
+ ```
206
+ See `RestClient::Resource` docs for details.
207
+
208
+ ## Exceptions (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
209
+
210
+ - for result codes between `200` and `207`, a `RestClient::Response` will be returned
211
+ - for result codes `301`, `302` or `307`, the redirection will be followed if the request is a `GET` or a `HEAD`
212
+ - for result code `303`, the redirection will be followed and the request transformed into a `GET`
213
+ - for other cases, a `RestClient::ExceptionWithResponse` holding the Response will be raised; a specific exception class will be thrown for known error codes
214
+ - call `.response` on the exception to get the server's response
215
+
216
+ ```ruby
217
+ >> RestClient.get 'http://example.com/nonexistent'
218
+ Exception: RestClient::NotFound: 404 Not Found
219
+
220
+ >> begin
221
+ RestClient.get 'http://example.com/nonexistent'
222
+ rescue RestClient::ExceptionWithResponse => e
223
+ e.response
224
+ end
225
+ => <RestClient::Response 404 "<!doctype h...">
226
+ ```
227
+
228
+ ### Other exceptions
229
+
230
+ While most exceptions have been collected under `RestClient::RequestFailed` aka
231
+ `RestClient::ExceptionWithResponse`, there are a few quirky exceptions that
232
+ have been kept for backwards compatibility.
233
+
234
+ RestClient will propagate up exceptions like socket errors without modification:
235
+
236
+ ```ruby
237
+ >> RestClient.get 'http://localhost:12345'
238
+ Exception: Errno::ECONNREFUSED: Connection refused - connect(2) for "localhost" port 12345
239
+ ```
240
+
241
+ RestClient handles a few specific error cases separately in order to give
242
+ better error messages. These will hopefully be cleaned up in a future major
243
+ release.
244
+
245
+ `RestClient::ServerBrokeConnection` is translated from `EOFError` to give a
246
+ better error message.
247
+
248
+ `RestClient::SSLCertificateNotVerified` is raised when HTTPS validation fails.
249
+ Other `OpenSSL::SSL::SSLError` errors are raised as is.
250
+
251
+ ### Redirection
252
+
253
+ By default, rest-client will follow HTTP 30x redirection requests.
254
+
255
+ __New in 2.0:__ `RestClient::Response` exposes a `#history` method that returns
256
+ a list of each response received in a redirection chain.
257
+
258
+ ```ruby
259
+ >> r = RestClient.get('http://httpbin.org/redirect/2')
260
+ => <RestClient::Response 200 "{\n \"args\":...">
261
+
262
+ # see each response in the redirect chain
263
+ >> r.history
264
+ => [<RestClient::Response 302 "<!DOCTYPE H...">, <RestClient::Response 302 "">]
265
+
266
+ # see each requested URL
267
+ >> r.request.url
268
+ => "http://httpbin.org/get"
269
+ >> r.history.map {|x| x.request.url}
270
+ => ["http://httpbin.org/redirect/2", "http://httpbin.org/relative-redirect/1"]
271
+ ```
272
+
273
+ #### Manually following redirection
274
+
275
+ To disable automatic redirection, set `:max_redirects => 0`.
276
+
277
+ __New in 2.0:__ Prior versions of rest-client would raise
278
+ `RestClient::MaxRedirectsReached`, with no easy way to access the server's
279
+ response. In 2.0, rest-client raises the normal
280
+ `RestClient::ExceptionWithResponse` as it would with any other non-HTTP-20x
281
+ response.
282
+
283
+ ```ruby
284
+ >> RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/1')
285
+ => RestClient::Response 200 "{\n "args":..."
286
+
287
+ >> RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/1', max_redirects: 0)
288
+ RestClient::Found: 302 Found
289
+ ```
290
+
291
+ To manually follow redirection, you can call `Response#follow_redirection`. Or
292
+ you could of course inspect the result and choose custom behavior.
293
+
294
+ ```ruby
295
+ >> RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/1', max_redirects: 0)
296
+ RestClient::Found: 302 Found
297
+ >> begin
298
+ RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/1', max_redirects: 0)
299
+ rescue RestClient::ExceptionWithResponse => err
300
+ end
301
+ >> err
302
+ => #<RestClient::Found: 302 Found>
303
+ >> err.response
304
+ => RestClient::Response 302 "<!DOCTYPE H..."
305
+ >> err.response.headers[:location]
306
+ => "/get"
307
+ >> err.response.follow_redirection
308
+ => RestClient::Response 200 "{\n "args":..."
309
+ ```
310
+
311
+ ## Result handling
312
+
313
+ The result of a `RestClient::Request` is a `RestClient::Response` object.
314
+
315
+ __New in 2.0:__ `RestClient::Response` objects are now a subclass of `String`.
316
+ Previously, they were a real String object with response functionality mixed
317
+ in, which was very confusing to work with.
318
+
319
+ Response objects have several useful methods. (See the class rdoc for more details.)
320
+
321
+ - `Response#code`: The HTTP response code
322
+ - `Response#body`: The response body as a string. (AKA .to_s)
323
+ - `Response#headers`: A hash of HTTP response headers
324
+ - `Response#raw_headers`: A hash of HTTP response headers as unprocessed arrays
325
+ - `Response#cookies`: A hash of HTTP cookies set by the server
326
+ - `Response#cookie_jar`: <em>New in 1.8</em> An HTTP::CookieJar of cookies
327
+ - `Response#request`: The RestClient::Request object used to make the request
328
+ - `Response#history`: <em>New in 2.0</em> If redirection was followed, a list of prior Response objects
329
+
330
+ ```ruby
331
+ RestClient.get('http://example.com')
332
+ ➔ <RestClient::Response 200 "<!doctype h...">
333
+
334
+ begin
335
+ RestClient.get('http://example.com/notfound')
336
+ rescue RestClient::ExceptionWithResponse => err
337
+ err.response
338
+ end
339
+ ➔ <RestClient::Response 404 "<!doctype h...">
340
+ ```
341
+
342
+ ### Response callbacks, error handling
343
+
344
+ A block can be passed to the RestClient method. This block will then be called with the Response.
345
+ Response.return! can be called to invoke the default response's behavior.
346
+
347
+ ```ruby
348
+ # Don't raise exceptions but return the response
349
+ >> RestClient.get('http://example.com/nonexistent') {|response, request, result| response }
350
+ => <RestClient::Response 404 "<!doctype h...">
351
+ ```
352
+
353
+ ```ruby
354
+ # Manage a specific error code
355
+ RestClient.get('http://example.com/resource') { |response, request, result, &block|
356
+ case response.code
357
+ when 200
358
+ p "It worked !"
359
+ response
360
+ when 423
361
+ raise SomeCustomExceptionIfYouWant
362
+ else
363
+ response.return!(&block)
364
+ end
365
+ }
366
+ ```
367
+
368
+ But note that it may be more straightforward to use exceptions to handle
369
+ different HTTP error response cases:
370
+
371
+ ```ruby
372
+ begin
373
+ resp = RestClient.get('http://example.com/resource')
374
+ rescue RestClient::Unauthorized, RestClient::Forbidden => err
375
+ puts 'Access denied'
376
+ return err.response
377
+ rescue RestClient::ImATeapot => err
378
+ puts 'The server is a teapot! # RFC 2324'
379
+ return err.response
380
+ else
381
+ puts 'It worked!'
382
+ return resp
383
+ end
384
+ ```
385
+
386
+ For GET and HEAD requests, rest-client automatically follows redirection. For
387
+ other HTTP verbs, call `.follow_redirection` on the response object (works both
388
+ in block form and in exception form).
389
+
390
+ ```ruby
391
+ # Follow redirections for all request types and not only for get and head
392
+ # RFC : "If the 301, 302 or 307 status code is received in response to a request other than GET or HEAD,
393
+ # the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user,
394
+ # since this might change the conditions under which the request was issued."
395
+
396
+ # block style
397
+ RestClient.post('http://example.com/redirect', 'body') { |response, request, result|
398
+ case response.code
399
+ when 301, 302, 307
400
+ response.follow_redirection
401
+ else
402
+ response.return!
403
+ end
404
+ }
405
+
406
+ # exception style by explicit classes
407
+ begin
408
+ RestClient.post('http://example.com/redirect', 'body')
409
+ rescue RestClient::MovedPermanently,
410
+ RestClient::Found,
411
+ RestClient::TemporaryRedirect => err
412
+ err.response.follow_redirection
413
+ end
414
+
415
+ # exception style by response code
416
+ begin
417
+ RestClient.post('http://example.com/redirect', 'body')
418
+ rescue RestClient::ExceptionWithResponse => err
419
+ case err.http_code
420
+ when 301, 302, 307
421
+ err.response.follow_redirection
422
+ else
423
+ raise
424
+ end
425
+ end
426
+ ```
427
+
428
+ ## Non-normalized URIs
429
+
430
+ If you need to normalize URIs, e.g. to work with International Resource Identifiers (IRIs),
431
+ use the addressable gem (http://addressable.rubyforge.org/api/) in your code:
432
+
433
+ ```ruby
434
+ require 'addressable/uri'
435
+ RestClient.get(Addressable::URI.parse("http://www.詹姆斯.com/").normalize.to_str)
436
+ ```
437
+
438
+ ## Lower-level access
439
+
440
+ For cases not covered by the general API, you can use the `RestClient::Request` class, which provides a lower-level API.
441
+
442
+ You can:
443
+
444
+ - specify ssl parameters
445
+ - override cookies
446
+ - manually handle the response (e.g. to operate on it as a stream rather than reading it all into memory)
447
+
448
+ See `RestClient::Request`'s documentation for more information.
449
+
450
+ ### Streaming request payload
451
+
452
+ RestClient will try to stream any file-like payload rather than reading it into
453
+ memory. This happens through `RestClient::Payload::Streamed`, which is
454
+ automatically called internally by `RestClient::Payload.generate` on anything
455
+ with a `read` method.
456
+
457
+ ```ruby
458
+ >> r = RestClient.put('http://httpbin.org/put', File.open('/tmp/foo.txt', 'r'),
459
+ content_type: 'text/plain')
460
+ => <RestClient::Response 200 "{\n \"args\":...">
461
+ ```
462
+
463
+ In Multipart requests, RestClient will also stream file handles passed as Hash
464
+ (or __new in 2.1__ ParamsArray).
465
+
466
+ ```ruby
467
+ >> r = RestClient.put('http://httpbin.org/put',
468
+ {file_a: File.open('a.txt', 'r'),
469
+ file_b: File.open('b.txt', 'r')})
470
+ => <RestClient::Response 200 "{\n \"args\":...">
471
+
472
+ # received by server as two file uploads with multipart/form-data
473
+ >> JSON.parse(r)['files'].keys
474
+ => ['file_a', 'file_b']
475
+ ```
476
+
477
+ ### Streaming responses
478
+
479
+ Normally, when you use `RestClient.get` or the lower level
480
+ `RestClient::Request.execute method: :get` to retrieve data, the entire
481
+ response is buffered in memory and returned as the response to the call.
482
+
483
+ However, if you are retrieving a large amount of data, for example a Docker
484
+ image, an iso, or any other large file, you may want to stream the response
485
+ directly to disk rather than loading it in memory. If you have a very large
486
+ file, it may become *impossible* to load it into memory.
487
+
488
+ There are two main ways to do this:
489
+
490
+ #### `raw_response`, saves into Tempfile
491
+
492
+ If you pass `raw_response: true` to `RestClient::Request.execute`, it will save
493
+ the response body to a temporary file (using `Tempfile`) and return a
494
+ `RestClient::RawResponse` object rather than a `RestClient::Response`.
495
+
496
+ Note that the tempfile created by `Tempfile.new` will be in `Dir.tmpdir`
497
+ (usually `/tmp/`), which you can override to store temporary files in a
498
+ different location. This file will be unlinked when it is dereferenced.
499
+
500
+ If logging is enabled, this will also print download progress.
501
+ __New in 2.1:__ Customize the interval with `:stream_log_percent` (defaults to
502
+ 10 for printing a message every 10% complete).
503
+
504
+ For example:
505
+
506
+ ```ruby
507
+ >> raw = RestClient::Request.execute(
508
+ method: :get,
509
+ url: 'http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso',
510
+ raw_response: true)
511
+ => <RestClient::RawResponse @code=200, @file=#<Tempfile:/tmp/rest-client.20170522-5346-1pptjm1>, @request=<RestClient::Request @method="get", @url="http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso">>
512
+ >> raw.file.size
513
+ => 1554186240
514
+ >> raw.file.path
515
+ => "/tmp/rest-client.20170522-5346-1pptjm1"
516
+ raw.file.path
517
+ => "/tmp/rest-client.20170522-5346-1pptjm1"
518
+
519
+ >> require 'digest/sha1'
520
+ >> Digest::SHA1.file(raw.file.path).hexdigest
521
+ => "4375b73e3a1aa305a36320ffd7484682922262b3"
522
+ ```
523
+
524
+ #### `block_response`, receives raw Net::HTTPResponse
525
+
526
+ If you want to stream the data from the response to a file as it comes, rather
527
+ than entirely in memory, you can also pass `RestClient::Request.execute` a
528
+ parameter `:block_response` to which you pass a block/proc. This block receives
529
+ the raw unmodified Net::HTTPResponse object from Net::HTTP, which you can use
530
+ to stream directly to a file as each chunk is received.
531
+
532
+ Note that this bypasses all the usual HTTP status code handling, so you will
533
+ want to do you own checking for HTTP 20x response codes, redirects, etc.
534
+
535
+ The following is an example:
536
+
537
+ ````ruby
538
+ File.open('/some/output/file', 'w') {|f|
539
+ block = proc { |response|
540
+ response.read_body do |chunk|
541
+ f.write chunk
542
+ end
543
+ }
544
+ RestClient::Request.execute(method: :get,
545
+ url: 'http://example.com/some/really/big/file.img',
546
+ block_response: block)
547
+ }
548
+ ````
549
+
550
+ ## Shell
551
+
552
+ The restclient shell command gives an IRB session with RestClient already loaded:
553
+
554
+ ```ruby
555
+ $ restclient
556
+ >> RestClient.get 'http://example.com'
557
+ ```
558
+
559
+ Specify a URL argument for get/post/put/delete on that resource:
560
+
561
+ ```ruby
562
+ $ restclient http://example.com
563
+ >> put '/resource', 'data'
564
+ ```
565
+
566
+ Add a user and password for authenticated resources:
567
+
568
+ ```ruby
569
+ $ restclient https://example.com user pass
570
+ >> delete '/private/resource'
571
+ ```
572
+
573
+ Create ~/.restclient for named sessions:
574
+
575
+ ```ruby
576
+ sinatra:
577
+ url: http://localhost:4567
578
+ rack:
579
+ url: http://localhost:9292
580
+ private_site:
581
+ url: http://example.com
582
+ username: user
583
+ password: pass
584
+ ```
585
+
586
+ Then invoke:
587
+
588
+ ```ruby
589
+ $ restclient private_site
590
+ ```
591
+
592
+ Use as a one-off, curl-style:
593
+
594
+ ```ruby
595
+ $ restclient get http://example.com/resource > output_body
596
+
597
+ $ restclient put http://example.com/resource < input_body
598
+ ```
599
+
600
+ ## Logging
601
+
602
+ To enable logging globally you can:
603
+
604
+ - set RestClient.log with a Ruby Logger
605
+
606
+ ```ruby
607
+ RestClient.log = STDOUT
608
+ ```
609
+
610
+ - or set an environment variable to avoid modifying the code (in this case you can use a file name, "stdout" or "stderr"):
611
+
612
+ ```ruby
613
+ $ RESTCLIENT_LOG=stdout path/to/my/program
614
+ ```
615
+
616
+ You can also set individual loggers when instantiating a Resource or making an
617
+ individual request:
618
+
619
+ ```ruby
620
+ resource = RestClient::Resource.new 'http://example.com/resource', log: Logger.new(STDOUT)
621
+ ```
622
+
623
+ ```ruby
624
+ RestClient::Request.execute(method: :get, url: 'http://example.com/foo', log: Logger.new(STDERR))
625
+ ```
626
+
627
+ All options produce logs like this:
628
+
629
+ ```ruby
630
+ RestClient.get "http://some/resource"
631
+ # => 200 OK | text/html 250 bytes
632
+ RestClient.put "http://some/resource", "payload"
633
+ # => 401 Unauthorized | application/xml 340 bytes
634
+ ```
635
+
636
+ Note that these logs are valid Ruby, so you can paste them into the `restclient`
637
+ shell or a script to replay your sequence of rest calls.
638
+
639
+ ## Proxy
640
+
641
+ All calls to RestClient, including Resources, will use the proxy specified by
642
+ `RestClient.proxy`:
643
+
644
+ ```ruby
645
+ RestClient.proxy = "http://proxy.example.com/"
646
+ RestClient.get "http://some/resource"
647
+ # => response from some/resource as proxied through proxy.example.com
648
+ ```
649
+
650
+ Often the proxy URL is set in an environment variable, so you can do this to
651
+ use whatever proxy the system is configured to use:
652
+
653
+ ```ruby
654
+ RestClient.proxy = ENV['http_proxy']
655
+ ```
656
+
657
+ __New in 2.0:__ Specify a per-request proxy by passing the :proxy option to
658
+ RestClient::Request. This will override any proxies set by environment variable
659
+ or by the global `RestClient.proxy` value.
660
+
661
+ ```ruby
662
+ RestClient::Request.execute(method: :get, url: 'http://example.com',
663
+ proxy: 'http://proxy.example.com')
664
+ # => single request proxied through the proxy
665
+ ```
666
+
667
+ This can be used to disable the use of a proxy for a particular request.
668
+
669
+ ```ruby
670
+ RestClient.proxy = "http://proxy.example.com/"
671
+ RestClient::Request.execute(method: :get, url: 'http://example.com', proxy: nil)
672
+ # => single request sent without a proxy
673
+ ```
674
+
675
+ ## Query parameters
676
+
677
+ Rest-client can render a hash as HTTP query parameters for GET/HEAD/DELETE
678
+ requests or as HTTP post data in `x-www-form-urlencoded` format for POST
679
+ requests.
680
+
681
+ __New in 2.0:__ Even though there is no standard specifying how this should
682
+ work, rest-client follows a similar convention to the one used by Rack / Rails
683
+ servers for handling arrays, nested hashes, and null values.
684
+
685
+ The implementation in
686
+ [./lib/rest-client/utils.rb](RestClient::Utils.encode_query_string)
687
+ closely follows
688
+ [Rack::Utils.build_nested_query](http://www.rubydoc.info/gems/rack/Rack/Utils#build_nested_query-class_method),
689
+ but treats empty arrays and hashes as `nil`. (Rack drops them entirely, which
690
+ is confusing behavior.)
691
+
692
+ If you don't like this behavior and want more control, just serialize params
693
+ yourself (e.g. with `URI.encode_www_form`) and add the query string to the URL
694
+ directly for GET parameters or pass the payload as a string for POST requests.
695
+
696
+ Basic GET params:
697
+ ```ruby
698
+ RestClient.get('https://httpbin.org/get', params: {foo: 'bar', baz: 'qux'})
699
+ # GET "https://httpbin.org/get?foo=bar&baz=qux"
700
+ ```
701
+
702
+ Basic `x-www-form-urlencoded` POST params:
703
+ ```ruby
704
+ >> r = RestClient.post('https://httpbin.org/post', {foo: 'bar', baz: 'qux'})
705
+ # POST "https://httpbin.org/post", data: "foo=bar&baz=qux"
706
+ => <RestClient::Response 200 "{\n \"args\":...">
707
+ >> JSON.parse(r.body)
708
+ => {"args"=>{},
709
+ "data"=>"",
710
+ "files"=>{},
711
+ "form"=>{"baz"=>"qux", "foo"=>"bar"},
712
+ "headers"=>
713
+ {"Accept"=>"*/*",
714
+ "Accept-Encoding"=>"gzip, deflate",
715
+ "Content-Length"=>"15",
716
+ "Content-Type"=>"application/x-www-form-urlencoded",
717
+ "Host"=>"httpbin.org"},
718
+ "json"=>nil,
719
+ "url"=>"https://httpbin.org/post"}
720
+ ```
721
+
722
+ JSON payload: rest-client does not speak JSON natively, so serialize your
723
+ payload to a string before passing it to rest-client.
724
+ ```ruby
725
+ >> payload = {'name' => 'newrepo', 'description': 'A new repo'}
726
+ >> RestClient.post('https://api.github.com/user/repos', payload.to_json, content_type: :json)
727
+ => <RestClient::Response 201 "{\"id\":75149...">
728
+ ```
729
+
730
+ Advanced GET params (arrays):
731
+ ```ruby
732
+ >> r = RestClient.get('https://http-params.herokuapp.com/get', params: {foo: [1,2,3]})
733
+ # GET "https://http-params.herokuapp.com/get?foo[]=1&foo[]=2&foo[]=3"
734
+ => <RestClient::Response 200 "Method: GET...">
735
+ >> puts r.body
736
+ query_string: "foo[]=1&foo[]=2&foo[]=3"
737
+ decoded: "foo[]=1&foo[]=2&foo[]=3"
738
+
739
+ GET:
740
+ {"foo"=>["1", "2", "3"]}
741
+ ```
742
+
743
+ Advanced GET params (nested hashes):
744
+ ```ruby
745
+ >> r = RestClient.get('https://http-params.herokuapp.com/get', params: {outer: {foo: 123, bar: 456}})
746
+ # GET "https://http-params.herokuapp.com/get?outer[foo]=123&outer[bar]=456"
747
+ => <RestClient::Response 200 "Method: GET...">
748
+ >> puts r.body
749
+ ...
750
+ query_string: "outer[foo]=123&outer[bar]=456"
751
+ decoded: "outer[foo]=123&outer[bar]=456"
752
+
753
+ GET:
754
+ {"outer"=>{"foo"=>"123", "bar"=>"456"}}
755
+ ```
756
+
757
+ __New in 2.0:__ The new `RestClient::ParamsArray` class allows callers to
758
+ provide ordering even to structured parameters. This is useful for unusual
759
+ cases where the server treats the order of parameters as significant or you
760
+ want to pass a particular key multiple times.
761
+
762
+ Multiple fields with the same name using ParamsArray:
763
+ ```ruby
764
+ >> RestClient.get('https://httpbin.org/get', params:
765
+ RestClient::ParamsArray.new([[:foo, 1], [:foo, 2]]))
766
+ # GET "https://httpbin.org/get?foo=1&foo=2"
767
+ ```
768
+
769
+ Nested ParamsArray:
770
+ ```ruby
771
+ >> RestClient.get('https://httpbin.org/get', params:
772
+ {foo: RestClient::ParamsArray.new([[:a, 1], [:a, 2]])})
773
+ # GET "https://httpbin.org/get?foo[a]=1&foo[a]=2"
774
+ ```
775
+
776
+ ## Headers
777
+
778
+ Request headers can be set by passing a ruby hash containing keys and values
779
+ representing header names and values:
780
+
781
+ ```ruby
782
+ # GET request with modified headers
783
+ RestClient.get 'http://example.com/resource', {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
784
+
785
+ # POST request with modified headers
786
+ RestClient.post 'http://example.com/resource', {:foo => 'bar', :baz => 'qux'}, {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
787
+
788
+ # DELETE request with modified headers
789
+ RestClient.delete 'http://example.com/resource', {:Authorization => 'Bearer cT0febFoD5lxAlNAXHo6g'}
790
+ ```
791
+
792
+ ## Timeouts
793
+
794
+ By default the timeout for a request is 60 seconds. Timeouts for your request can
795
+ be adjusted by setting the `timeout:` to the number of seconds that you would like
796
+ the request to wait. Setting `timeout:` will override both `read_timeout:` and `open_timeout:`.
797
+
798
+ ```ruby
799
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
800
+ timeout: 120)
801
+ ```
802
+
803
+ Additionally, you can set `read_timeout:` and `open_timeout:` separately.
804
+
805
+ ```ruby
806
+ RestClient::Request.execute(method: :get, url: 'http://example.com/resource',
807
+ read_timeout: 120, open_timeout: 240)
808
+ ```
809
+
810
+ ## Cookies
811
+
812
+ Request and Response objects know about HTTP cookies, and will automatically
813
+ extract and set headers for them as needed:
814
+
815
+ ```ruby
816
+ response = RestClient.get 'http://example.com/action_which_sets_session_id'
817
+ response.cookies
818
+ # => {"_applicatioN_session_id" => "1234"}
819
+
820
+ response2 = RestClient.post(
821
+ 'http://localhost:3000/',
822
+ {:param1 => "foo"},
823
+ {:cookies => {:session_id => "1234"}}
824
+ )
825
+ # ...response body
826
+ ```
827
+ ### Full cookie jar support (new in 1.8)
828
+
829
+ The original cookie implementation was very naive and ignored most of the
830
+ cookie RFC standards.
831
+ __New in 1.8__: An HTTP::CookieJar of cookies
832
+
833
+ Response objects now carry a cookie_jar method that exposes an HTTP::CookieJar
834
+ of cookies, which supports full standards compliant behavior.
835
+
836
+ ## SSL/TLS support
837
+
838
+ Various options are supported for configuring rest-client's TLS settings. By
839
+ default, rest-client will verify certificates using the system's CA store on
840
+ all platforms. (This is intended to be similar to how browsers behave.) You can
841
+ specify an :ssl_ca_file, :ssl_ca_path, or :ssl_cert_store to customize the
842
+ certificate authorities accepted.
843
+
844
+ ### SSL Client Certificates
845
+
846
+ ```ruby
847
+ RestClient::Resource.new(
848
+ 'https://example.com',
849
+ :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read("cert.pem")),
850
+ :ssl_client_key => OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
851
+ :ssl_ca_file => "ca_certificate.pem",
852
+ :verify_ssl => OpenSSL::SSL::VERIFY_PEER
853
+ ).get
854
+ ```
855
+ Self-signed certificates can be generated with the openssl command-line tool.
856
+
857
+ ## Hook
858
+
859
+ RestClient.add_before_execution_proc add a Proc to be called before each execution.
860
+ It's handy if you need direct access to the HTTP request.
861
+
862
+ Example:
863
+
864
+ ```ruby
865
+ # Add oauth support using the oauth gem
866
+ require 'oauth'
867
+ access_token = ...
868
+
869
+ RestClient.add_before_execution_proc do |req, params|
870
+ access_token.sign! req
871
+ end
872
+
873
+ RestClient.get 'http://example.com'
874
+ ```
875
+
876
+ ## More
877
+
878
+ Need caching, more advanced logging or any ability provided by Rack middleware?
879
+
880
+ Have a look at rest-client-components: http://github.com/crohr/rest-client-components
881
+
882
+ ## Credits
883
+ | | |
884
+ |-------------------------|---------------------------------------------------------|
885
+ | **REST Client Team** | Andy Brody |
886
+ | **Creator** | Adam Wiggins |
887
+ | **Maintainers Emeriti** | Lawrence Leonard Gilbert, Matthew Manning, Julien Kirch |
888
+ | **Major contributions** | Blake Mizerany, Julien Kirch |
889
+
890
+ A great many generous folks have contributed features and patches.
891
+ See AUTHORS for the full list.
892
+
893
+ ## Legal
894
+
895
+ Released under the MIT License: https://opensource.org/licenses/MIT
896
+
897
+ Photo of the International Space Station was produced by NASA and is in the
898
+ public domain.
899
+
900
+ Code for reading Windows root certificate store derived from work by Puppet;
901
+ used under terms of the Apache License, Version 2.0.