rest-client 1.1.0 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rest-client might be problematic. Click here for more details.

@@ -1,24 +1,54 @@
1
- = REST Client -- simple DSL for accessing REST resources
1
+ = REST Client -- simple DSL for accessing HTTP and REST resources
2
2
 
3
- A simple REST client for Ruby, inspired by the Sinatra's microframework style
3
+ A simple HTTP and REST client for Ruby, inspired by the Sinatra's microframework style
4
4
  of specifying actions: get, put, post, delete.
5
5
 
6
+ * Main page: http://github.com/archiloque/rest-client
7
+ * Mailing list: rest.client@librelist.com (send a mail to subscribe).
8
+
6
9
  == Usage: Raw URL
7
10
 
8
11
  require 'rest_client'
9
12
 
10
13
  RestClient.get 'http://example.com/resource'
11
- RestClient.get 'https://user:password@example.com/private/resource'
14
+
15
+ RestClient.get 'http://example.com/resource', {:params => {:id => 50, 'foo' => 'bar'}}
16
+
17
+ RestClient.get 'https://user:password@example.com/private/resource', {:accept => :json}
12
18
 
13
19
  RestClient.post 'http://example.com/resource', :param1 => 'one', :nested => { :param2 => 'two' }
14
20
 
21
+ RestClient.post "http://example.com/resource", { 'x' => 1 }.to_json, :content_type => :json, :accept => :json
22
+
15
23
  RestClient.delete 'http://example.com/resource'
16
24
 
25
+ response = RestClient.get 'http://example.com/resource'
26
+ response.code
27
+ ➔ 200
28
+ response.cookies
29
+ ➔ {"Foo"=>"BAR", "QUUX"=>"QUUUUX"}
30
+ response.headers
31
+ ➔ {:content_type=>"text/html; charset=utf-8", :cache_control=>"private" ...
32
+ response.to_str
33
+ ➔ \n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n \"http://www.w3.org/TR/html4/strict.dtd\">\n\n<html ....
34
+
35
+ RestClient.post( url,
36
+ {
37
+ :transfer => {
38
+ :path => '/foo/bar',
39
+ :owner => 'that_guy',
40
+ :group => 'those_guys'
41
+ },
42
+ :upload => {
43
+ :file => File.new(path, 'rb')
44
+ }
45
+ })
46
+
17
47
  == Multipart
18
48
 
19
49
  Yeah, that's right! This does multipart sends for you!
20
50
 
21
- RestClient.post '/data', :myfile => File.new("/path/to/image.jpg")
51
+ RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb')
22
52
 
23
53
  This does two things for you:
24
54
 
@@ -46,9 +76,75 @@ See RestClient::Resource module docs for details.
46
76
 
47
77
  See RestClient::Resource docs for details.
48
78
 
79
+ == Exceptions (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
80
+
81
+ * for results code between 200 and 207 a RestClient::Response will be returned
82
+ * for results code 301, 302 or 307 the redirection will be followed if the request is a get or a head
83
+ * for result code 303 the redirection will be followed and the request transformed into a get
84
+ * for other cases a RestClient::Exception holding the Response will be raised, a specific exception class will be thrown for know error codes
85
+
86
+ RestClient.get 'http://example.com/resource'
87
+ ➔ RestClient::ResourceNotFound: RestClient::ResourceNotFound
88
+
89
+ begin
90
+ RestClient.get 'http://example.com/resource'
91
+ rescue => e
92
+ e.response
93
+ end
94
+ ➔ 404 Resource Not Found | text/html 282 bytes
95
+
96
+ == Result handling
97
+
98
+ A block can be passed to the RestClient method, this block will then be called with the Response.
99
+ Response.return! can be called to invoke the default response's behavior.
100
+
101
+ # Don't raise exceptions but return the response
102
+ RestClient.get('http://example.com/resource'){|response, request, result| response }
103
+ ➔ 404 Resource Not Found | text/html 282 bytes
104
+
105
+ # Manage a specific error code
106
+ RestClient.get('http://my-rest-service.com/resource'){ |response, request, result, &block|
107
+ case response.code
108
+ when 200
109
+ p "It worked !"
110
+ response
111
+ when 423
112
+ raise SomeCustomExceptionIfYouWant
113
+ else
114
+ response.return!(request, result, &block)
115
+ end
116
+ }
117
+
118
+ # Follow redirections for all request types and not only for get and head
119
+ # RFC : "If the 301, 302 or 307 status code is received in response to a request other than GET or HEAD,
120
+ # the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user,
121
+ # since this might change the conditions under which the request was issued."
122
+ RestClient.get('http://my-rest-service.com/resource'){ |response, request, result, &block|
123
+ if [301, 302, 307].include? response.code
124
+ response.follow_redirection(request, result, &block)
125
+ else
126
+ response.return!(request, result, &block)
127
+ end
128
+ }
129
+
130
+ == Non-normalized URIs.
131
+
132
+ If you want to use non-normalized URIs, you can normalize them with the addressable gem (http://addressable.rubyforge.org/api/).
133
+
134
+ require 'addressable/uri'
135
+ RestClient.get(Addressable::URI.parse("http://www.詹姆斯.com/").normalize.to_str)
136
+
49
137
  == Lower-level access
50
138
 
51
- For cases not covered by the general API, you can use the RestClient::Resource class which provide a lower-level API, see the class' rdoc for more information.
139
+ For cases not covered by the general API, you can use the RestClient::Request class which provide a lower-level API.
140
+
141
+ You can:
142
+
143
+ * specify ssl parameters
144
+ * override cookies
145
+ * manually handle the response (so you can operate on the response stream than reading it fully in memory)
146
+
147
+ see the class' rdoc for more information.
52
148
 
53
149
  == Shell
54
150
 
@@ -82,18 +178,99 @@ Then invoke:
82
178
 
83
179
  $ restclient private_site
84
180
 
85
- == Meta
181
+ Use as a one-off, curl-style:
86
182
 
87
- Written by Adam Wiggins, major modifications by Blake Mizerany, maintained by Archiloque
183
+ $ restclient get http://example.com/resource > output_body
88
184
 
89
- Patches contributed by: Chris Anderson, Greg Borenstein, Ardekantur, Pedro Belo, Rafael Souza, Rick Olson, Aman Gupta, François Beausoleil and Nick Plante.
185
+ $ restclient put http://example.com/resource < input_body
90
186
 
91
- Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
187
+ == Logging
188
+
189
+ To enable logging you can
190
+
191
+ * set RestClient.log with a ruby Logger
192
+ * or set an environment variable to avoid modifying the code (in this case you can use a file name, "stdout" or "stderr"):
193
+
194
+ $ RESTCLIENT_LOG=stdout path/to/my/program
195
+
196
+ Either produces logs like this:
197
+
198
+ RestClient.get "http://some/resource"
199
+ # => 200 OK | text/html 250 bytes
200
+ RestClient.put "http://some/resource", "payload"
201
+ # => 401 Unauthorized | application/xml 340 bytes
202
+
203
+ Note that these logs are valid Ruby, so you can paste them into the restclient
204
+ shell or a script to replay your sequence of rest calls.
205
+
206
+ == Proxy
207
+
208
+ All calls to RestClient, including Resources, will use the proxy specified by
209
+ RestClient.proxy:
210
+
211
+ RestClient.proxy = "http://proxy.example.com/"
212
+ RestClient.get "http://some/resource"
213
+ # => response from some/resource as proxied through proxy.example.com
92
214
 
93
- Main page: http://github.com/archiloque/rest-client
215
+ Often the proxy url is set in an environment variable, so you can do this to
216
+ use whatever proxy the system is configured to use:
94
217
 
95
- Rdoc: http://rdoc.info/projects/archiloque/rest-client
218
+ RestClient.proxy = ENV['http_proxy']
96
219
 
97
- Mailing list: rest.client@librelist.com (send a mail to subscribe).
220
+ == Cookies
98
221
 
99
- IRC: #rest-client at freenode
222
+ Request and Response objects know about HTTP cookies, and will automatically
223
+ extract and set headers for them as needed:
224
+
225
+ response = RestClient.get 'http://example.com/action_which_sets_session_id'
226
+ response.cookies
227
+ # => {"_applicatioN_session_id" => "1234"}
228
+
229
+ response2 = RestClient.post(
230
+ 'http://localhost:3000/',
231
+ {:param1 => "foo"},
232
+ {:cookies => {:session_id => "1234"}}
233
+ )
234
+ # ...response body
235
+
236
+ == SSL Client Certificates
237
+
238
+ RestClient::Resource.new(
239
+ 'https://example.com',
240
+ :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read("cert.pem")),
241
+ :ssl_client_key => OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
242
+ :ssl_ca_file => "ca_certificate.pem",
243
+ :verify_ssl => OpenSSL::SSL::VERIFY_PEER
244
+ ).get
245
+
246
+ Self-signed certificates can be generated with the openssl command-line tool.
247
+
248
+ == Hook
249
+
250
+ RestClient.add_before_execution_proc add a Proc to be called before each execution, it's handy if you need a direct access to the http request.
251
+
252
+ Example:
253
+
254
+ # Add oath support using the oauth gem
255
+ require 'oauth'
256
+ access_token = ...
257
+
258
+ RestClient.add_before_execution_proc do |req, params|
259
+ access_token.sign! req
260
+ end
261
+
262
+ RestClient.get 'http://example.com'
263
+
264
+ == More
265
+
266
+ Need caching, more advanced logging or any ability provided by a rack middleware ?
267
+
268
+ Have a look at rest-client-components http://github.com/crohr/rest-client-components
269
+
270
+ == Meta
271
+
272
+ Written by Adam Wiggins, major modifications by Blake Mizerany, maintained by Julien Kirch
273
+
274
+ Patches contributed by many, including Chris Anderson, Greg Borenstein, Ardekantur, Pedro Belo, Rafael Souza, Rick Olson, Aman Gupta, François Beausoleil and Nick Plante.
275
+
276
+ Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
data/Rakefile CHANGED
@@ -3,41 +3,50 @@ require 'rake'
3
3
  require 'jeweler'
4
4
 
5
5
  Jeweler::Tasks.new do |s|
6
- s.name = "rest-client"
7
- s.description = "A simple REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete."
8
- s.summary = "Simple REST client for Ruby, inspired by microframework syntax for specifying actions."
9
- s.author = "Adam Wiggins"
10
- s.email = "adam@heroku.com"
11
- s.homepage = "http://rest-client.heroku.com/"
12
- s.rubyforge_project = "rest-client"
13
- s.has_rdoc = true
14
- s.files = FileList["[A-Z]*", "{bin,lib,spec}/**/*"]
15
- s.executables = %w(restclient)
6
+ s.name = "rest-client"
7
+ s.description = "A simple HTTP and REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete."
8
+ s.summary = "Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions."
9
+ s.authors = ["Adam Wiggins", "Julien Kirch"]
10
+ s.email = "rest.client@librelist.com"
11
+ s.homepage = "http://github.com/archiloque/rest-client"
12
+ s.files = FileList["[A-Z]*", "{bin,lib,spec}/**/*"]
13
+ s.test_files = FileList["{spec}/**/*"]
14
+ s.add_runtime_dependency("mime-types", ">= 1.16")
15
+ s.add_development_dependency("webmock", ">= 0.9.1")
16
+ s.add_development_dependency("rspec")
17
+ s.extra_rdoc_files = [ 'README.rdoc', 'history.md']
16
18
  end
17
19
 
18
- Jeweler::RubyforgeTasks.new
19
-
20
20
  ############################
21
21
 
22
22
  require 'spec/rake/spectask'
23
23
 
24
24
  desc "Run all specs"
25
- Spec::Rake::SpecTask.new('spec') do |t|
26
- t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
27
- t.spec_files = FileList['spec/*_spec.rb']
25
+ task :spec => ["spec:unit", "spec:integration"]
26
+
27
+ desc "Run unit specs"
28
+ Spec::Rake::SpecTask.new('spec:unit') do |t|
29
+ t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
30
+ t.spec_files = FileList['spec/*_spec.rb']
31
+ end
32
+
33
+ desc "Run integration specs"
34
+ Spec::Rake::SpecTask.new('spec:integration') do |t|
35
+ t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
36
+ t.spec_files = FileList['spec/integration/*_spec.rb']
28
37
  end
29
38
 
30
39
  desc "Print specdocs"
31
40
  Spec::Rake::SpecTask.new(:doc) do |t|
32
- t.spec_opts = ["--format", "specdoc", "--dry-run"]
33
- t.spec_files = FileList['spec/*_spec.rb']
41
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
42
+ t.spec_files = FileList['spec/*_spec.rb']
34
43
  end
35
44
 
36
45
  desc "Run all examples with RCov"
37
46
  Spec::Rake::SpecTask.new('rcov') do |t|
38
- t.spec_files = FileList['spec/*_spec.rb']
39
- t.rcov = true
40
- t.rcov_opts = ['--exclude', 'examples']
47
+ t.spec_files = FileList['spec/*_spec.rb']
48
+ t.rcov = true
49
+ t.rcov_opts = ['--exclude', 'examples']
41
50
  end
42
51
 
43
52
  task :default => :spec
@@ -47,11 +56,11 @@ task :default => :spec
47
56
  require 'rake/rdoctask'
48
57
 
49
58
  Rake::RDocTask.new do |t|
50
- t.rdoc_dir = 'rdoc'
51
- t.title = "rest-client, fetch RESTful resources effortlessly"
52
- t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
53
- t.options << '--charset' << 'utf-8'
54
- t.rdoc_files.include('README.rdoc')
55
- t.rdoc_files.include('lib/*.rb')
59
+ t.rdoc_dir = 'rdoc'
60
+ t.title = "rest-client, fetch RESTful resources effortlessly"
61
+ t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
62
+ t.options << '--charset' << 'utf-8'
63
+ t.rdoc_files.include('README.rdoc')
64
+ t.rdoc_files.include('lib/*.rb')
56
65
  end
57
66
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.6.3
@@ -6,17 +6,19 @@ require 'restclient'
6
6
  require "yaml"
7
7
 
8
8
  def usage(why = nil)
9
- puts "failed for reason: #{why}" if why
10
- puts "usage: restclient [get|put|post|delete] url|name [username] [password]"
11
- puts " The verb is optional, if you leave it off you'll get an interactive shell."
12
- puts " put and post both take the input body on stdin."
13
- exit(1)
9
+ puts "failed for reason: #{why}" if why
10
+ puts "usage: restclient [get|put|post|delete] url|name [username] [password]"
11
+ puts " The verb is optional, if you leave it off you'll get an interactive shell."
12
+ puts " put and post both take the input body on stdin."
13
+ exit(1)
14
14
  end
15
15
 
16
- if %w(get put post delete).include? ARGV.first
17
- @verb = ARGV.shift
16
+ POSSIBLE_VERBS = ['get', 'put', 'post', 'delete']
17
+
18
+ if POSSIBLE_VERBS.include? ARGV.first
19
+ @verb = ARGV.shift
18
20
  else
19
- @verb = nil
21
+ @verb = nil
20
22
  end
21
23
 
22
24
  @url = ARGV.shift || 'http://localhost:4567'
@@ -24,61 +26,64 @@ end
24
26
  config = YAML.load(File.read(ENV['HOME'] + "/.restclient")) rescue {}
25
27
 
26
28
  @url, @username, @password = if c = config[@url]
27
- [c['url'], c['username'], c['password']]
29
+ [c['url'], c['username'], c['password']]
28
30
  else
29
- [@url, *ARGV]
31
+ [@url, * ARGV]
30
32
  end
31
33
 
32
34
  usage("invalid url '#{@url}") unless @url =~ /^https?/
33
35
  usage("too few args") unless ARGV.size < 3
34
36
 
35
37
  def r
36
- @r ||= RestClient::Resource.new(@url, @username, @password)
38
+ @r ||= RestClient::Resource.new(@url, @username, @password)
37
39
  end
38
40
 
39
41
  r # force rc to load
40
42
 
41
43
  if @verb
42
- begin
43
- if %w(put post).include? @verb
44
- puts r.send(@verb, STDIN.read)
45
- else
46
- puts r.send(@verb)
47
- end
48
- exit 0
49
- rescue RestClient::Exception => e
50
- puts e.response.body if e.respond_to? :response
51
- raise
52
- end
44
+ begin
45
+ if %w( put post ).include? @verb
46
+ puts r.send(@verb, STDIN.read)
47
+ else
48
+ puts r.send(@verb)
49
+ end
50
+ exit 0
51
+ rescue RestClient::Exception => e
52
+ puts e.response.body if e.respond_to? :response
53
+ raise
54
+ end
53
55
  end
54
56
 
55
- %w(get post put delete).each do |m|
56
- eval <<-end_eval
57
- def #{m}(path, *args, &b)
58
- r[path].#{m}(*args, &b)
57
+ POSSIBLE_VERBS.each do |m|
58
+ eval <<-end_eval
59
+ def #{m} (path, *args, &b)
60
+ r[path]. #{m} (*args, &b)
59
61
  end
60
- end_eval
62
+ end_eval
61
63
  end
62
64
 
63
- def method_missing(s, *args, &b)
64
- super unless r.respond_to?(s)
65
- begin
66
- r.send(s, *args, &b)
67
- rescue RestClient::RequestFailed => e
68
- print STDERR, e.response.body
69
- raise e
70
- end
65
+ def method_missing(s, * args, & b)
66
+ if POSSIBLE_VERBS.include? s
67
+ begin
68
+ r.send(s, *args, & b)
69
+ rescue RestClient::RequestFailed => e
70
+ print STDERR, e.response.body
71
+ raise e
72
+ end
73
+ else
74
+ super
75
+ end
71
76
  end
72
77
 
73
78
  require 'irb'
74
79
  require 'irb/completion'
75
80
 
76
81
  if File.exists? ".irbrc"
77
- ENV['IRBRC'] = ".irbrc"
82
+ ENV['IRBRC'] = ".irbrc"
78
83
  end
79
84
 
80
- if File.exists?(rcfile = "~/.restclientrc")
81
- load(rcfile)
85
+ if File.exists?(File.expand_path(rcfile = "~/.restclientrc"))
86
+ load(rcfile)
82
87
  end
83
88
 
84
89
  ARGV.clear