2008-03-10 20:20:57 -04:00
|
|
|
module RestClient
|
2009-12-29 12:27:39 -05:00
|
|
|
# A class that can be instantiated for access to a RESTful resource,
|
|
|
|
# including authentication.
|
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
#
|
|
|
|
# resource = RestClient::Resource.new('http://some/resource')
|
|
|
|
# jpg = resource.get(:accept => 'image/jpg')
|
|
|
|
#
|
|
|
|
# With HTTP basic authentication:
|
|
|
|
#
|
|
|
|
# resource = RestClient::Resource.new('http://protected/resource', :user => 'user', :password => 'password')
|
|
|
|
# resource.delete
|
|
|
|
#
|
|
|
|
# With a timeout (seconds):
|
|
|
|
#
|
2015-03-14 18:18:36 -04:00
|
|
|
# RestClient::Resource.new('http://slow', :read_timeout => 10)
|
2009-12-29 12:27:39 -05:00
|
|
|
#
|
|
|
|
# With an open timeout (seconds):
|
|
|
|
#
|
|
|
|
# RestClient::Resource.new('http://behindfirewall', :open_timeout => 10)
|
|
|
|
#
|
|
|
|
# You can also use resources to share common headers. For headers keys,
|
|
|
|
# symbols are converted to strings. Example:
|
|
|
|
#
|
|
|
|
# resource = RestClient::Resource.new('http://some/resource', :headers => { :client_version => 1 })
|
|
|
|
#
|
|
|
|
# This header will be transported as X-Client-Version (notice the X prefix,
|
|
|
|
# capitalization and hyphens)
|
|
|
|
#
|
|
|
|
# Use the [] syntax to allocate subresources:
|
|
|
|
#
|
|
|
|
# site = RestClient::Resource.new('http://example.com', :user => 'adam', :password => 'mypasswd')
|
|
|
|
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
|
|
|
#
|
|
|
|
class Resource
|
2010-01-27 16:54:18 -05:00
|
|
|
attr_reader :url, :options, :block
|
2008-03-10 20:20:57 -04:00
|
|
|
|
2010-01-27 16:54:18 -05:00
|
|
|
def initialize(url, options={}, backwards_compatibility=nil, &block)
|
2009-12-29 12:27:39 -05:00
|
|
|
@url = url
|
2010-01-27 16:54:18 -05:00
|
|
|
@block = block
|
2009-12-29 12:27:39 -05:00
|
|
|
if options.class == Hash
|
|
|
|
@options = options
|
|
|
|
else # compatibility with previous versions
|
|
|
|
@options = { :user => options, :password => backwards_compatibility }
|
|
|
|
end
|
|
|
|
end
|
2008-03-10 20:20:57 -04:00
|
|
|
|
2010-01-27 16:54:18 -05:00
|
|
|
def get(additional_headers={}, &block)
|
2009-12-29 12:27:39 -05:00
|
|
|
headers = (options[:headers] || {}).merge(additional_headers)
|
|
|
|
Request.execute(options.merge(
|
|
|
|
:method => :get,
|
|
|
|
:url => url,
|
2010-01-27 16:54:18 -05:00
|
|
|
:headers => headers), &(block || @block))
|
2009-12-29 12:27:39 -05:00
|
|
|
end
|
2008-03-10 20:20:57 -04:00
|
|
|
|
2010-09-22 12:36:37 -04:00
|
|
|
def head(additional_headers={}, &block)
|
|
|
|
headers = (options[:headers] || {}).merge(additional_headers)
|
|
|
|
Request.execute(options.merge(
|
|
|
|
:method => :head,
|
|
|
|
:url => url,
|
|
|
|
:headers => headers), &(block || @block))
|
|
|
|
end
|
|
|
|
|
2010-01-27 16:54:18 -05:00
|
|
|
def post(payload, additional_headers={}, &block)
|
2009-12-29 12:27:39 -05:00
|
|
|
headers = (options[:headers] || {}).merge(additional_headers)
|
|
|
|
Request.execute(options.merge(
|
|
|
|
:method => :post,
|
|
|
|
:url => url,
|
|
|
|
:payload => payload,
|
2010-01-27 16:54:18 -05:00
|
|
|
:headers => headers), &(block || @block))
|
2009-12-29 12:27:39 -05:00
|
|
|
end
|
2008-03-10 20:20:57 -04:00
|
|
|
|
2010-01-27 16:54:18 -05:00
|
|
|
def put(payload, additional_headers={}, &block)
|
2009-12-29 12:27:39 -05:00
|
|
|
headers = (options[:headers] || {}).merge(additional_headers)
|
|
|
|
Request.execute(options.merge(
|
|
|
|
:method => :put,
|
|
|
|
:url => url,
|
|
|
|
:payload => payload,
|
2010-01-27 16:54:18 -05:00
|
|
|
:headers => headers), &(block || @block))
|
2009-12-29 12:27:39 -05:00
|
|
|
end
|
2008-03-10 20:20:57 -04:00
|
|
|
|
2011-04-29 18:17:47 -04:00
|
|
|
def patch(payload, additional_headers={}, &block)
|
|
|
|
headers = (options[:headers] || {}).merge(additional_headers)
|
|
|
|
Request.execute(options.merge(
|
|
|
|
:method => :patch,
|
|
|
|
:url => url,
|
|
|
|
:payload => payload,
|
|
|
|
:headers => headers), &(block || @block))
|
|
|
|
end
|
|
|
|
|
2010-01-27 16:54:18 -05:00
|
|
|
def delete(additional_headers={}, &block)
|
2009-12-29 12:27:39 -05:00
|
|
|
headers = (options[:headers] || {}).merge(additional_headers)
|
|
|
|
Request.execute(options.merge(
|
|
|
|
:method => :delete,
|
|
|
|
:url => url,
|
2010-01-27 16:54:18 -05:00
|
|
|
:headers => headers), &(block || @block))
|
2009-12-29 12:27:39 -05:00
|
|
|
end
|
2008-10-13 20:44:04 -04:00
|
|
|
|
2009-12-29 12:27:39 -05:00
|
|
|
def to_s
|
|
|
|
url
|
|
|
|
end
|
2008-11-01 20:23:38 -04:00
|
|
|
|
2009-12-29 12:27:39 -05:00
|
|
|
def user
|
|
|
|
options[:user]
|
|
|
|
end
|
2008-10-13 20:44:04 -04:00
|
|
|
|
2009-12-29 12:27:39 -05:00
|
|
|
def password
|
|
|
|
options[:password]
|
|
|
|
end
|
2008-10-13 20:44:04 -04:00
|
|
|
|
2009-12-29 12:27:39 -05:00
|
|
|
def headers
|
|
|
|
options[:headers] || {}
|
|
|
|
end
|
2008-06-20 23:18:32 -04:00
|
|
|
|
2015-03-14 18:18:36 -04:00
|
|
|
def read_timeout
|
|
|
|
options[:read_timeout]
|
2009-12-29 12:27:39 -05:00
|
|
|
end
|
2008-12-08 04:47:23 -05:00
|
|
|
|
2009-12-29 12:27:39 -05:00
|
|
|
def open_timeout
|
|
|
|
options[:open_timeout]
|
|
|
|
end
|
2008-06-20 23:18:32 -04:00
|
|
|
|
2009-12-29 12:27:39 -05:00
|
|
|
# Construct a subresource, preserving authentication.
|
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
#
|
|
|
|
# site = RestClient::Resource.new('http://example.com', 'adam', 'mypasswd')
|
|
|
|
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
|
|
|
#
|
|
|
|
# This is especially useful if you wish to define your site in one place and
|
|
|
|
# call it in multiple locations:
|
|
|
|
#
|
|
|
|
# def orders
|
|
|
|
# RestClient::Resource.new('http://example.com/orders', 'admin', 'mypasswd')
|
|
|
|
# end
|
|
|
|
#
|
|
|
|
# orders.get # GET http://example.com/orders
|
|
|
|
# orders['1'].get # GET http://example.com/orders/1
|
|
|
|
# orders['1/items'].delete # DELETE http://example.com/orders/1/items
|
|
|
|
#
|
|
|
|
# Nest resources as far as you want:
|
|
|
|
#
|
|
|
|
# site = RestClient::Resource.new('http://example.com')
|
|
|
|
# posts = site['posts']
|
|
|
|
# first_post = posts['1']
|
|
|
|
# comments = first_post['comments']
|
|
|
|
# comments.post 'Hello', :content_type => 'text/plain'
|
|
|
|
#
|
2010-07-03 07:30:58 -04:00
|
|
|
def [](suburl, &new_block)
|
|
|
|
case
|
2014-07-08 06:54:01 -04:00
|
|
|
when block_given? then self.class.new(concat_urls(url, suburl), options, &new_block)
|
|
|
|
when block then self.class.new(concat_urls(url, suburl), options, &block)
|
|
|
|
else self.class.new(concat_urls(url, suburl), options)
|
2010-07-03 07:30:58 -04:00
|
|
|
end
|
2009-12-29 12:27:39 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def concat_urls(url, suburl) # :nodoc:
|
|
|
|
url = url.to_s
|
|
|
|
suburl = suburl.to_s
|
|
|
|
if url.slice(-1, 1) == '/' or suburl.slice(0, 1) == '/'
|
|
|
|
url + suburl
|
|
|
|
else
|
|
|
|
"#{url}/#{suburl}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2008-03-10 20:20:57 -04:00
|
|
|
end
|