Object
A very simple REST client, best explained by example:
# Retrieve a Kitten and print its name and colour kitten = Restr.get('http://example.com/kittens/1.xml') puts kitten['name'] puts kitten['colour'] # Create a Kitten kitten = Restr.post('http://example.com/kittens.xml', :name => 'batman', :colour => 'black') # Update a Kitten kitten = Restr.put('http://example.com/kittens/1.xml', :age => '6 months') # Delete a Kitten :( kitten = Restr.delete('http://example.com/kittens/1.xml') # Retrieve a list of Kittens kittens = Restr.get('http://example.com/kittens.xml')
When the response to a Restr request has content type 'text/xml', the response body will be parsed from XML into a nested Hash (using XmlSimple -- see xml-simple.rubyforge.org/). Otherwise the response is returned untouched, as a String.
If the remote REST resource requires authentication (Restr only supports HTTP Basic authentication, for now):
Restr.get('http://example.com/kittens/1.xml, {}, {:username => 'foo', :password => 'bar'})
A standard Ruby Logger can be attached to the Restr client like so:
logger = Logger.new('restr.log') logger.level = Logger::DEBUG Restr.logger = logger
Restr will now log its activity to the given Logger. The default_logger can be overridden by supplying a :logger option to a client call:
kitten_logger = Logger.new('kitten.log'} Restr.get('http://example.com/kittens/1.xml, {}, {:logger => kitten_logger)
# File lib/restr.rb, line 102 def self.do(method, url, params = {}, options = {}) puts "METHOD: #{method.inspect}" puts "URL: #{url.inspect}" puts "PARAMS: #{params.inspect}" puts "OPTIONS: #{options.inspect}" uri = URI.parse(url) params = {} unless params options = {} unless options logger = options[:logger] || self.logger method_mod = method.to_s.downcase.capitalize unless Net::HTTP.const_defined?(method_mod) raise InvalidRequestMethod, "Callback method #{method.inspect} is not a valid HTTP request method." end if method_mod == 'Get' q = params.collect{|k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"}.join("&") if uri.query uri.query += "&#{q}" else uri.query = q end end req = Net::HTTP.const_get(method_mod).new(uri.request_uri) if options[:username] || options['username'] req.basic_auth options[:username] || options['username'], options[:password] || options['password'] end if params.kind_of?(Hash) && method_mod != 'Get' && method_mod != 'get' req.set_form_data(params, '&') end logger.debug("Sending #{method.inspect} request to #{url.inspect} with data #{params.inspect}"+ (options ? " with options" : "")+".") if logger client = Net::HTTP.new(uri.host, uri.port) client.use_ssl = (uri.scheme == 'https') timeout = Restr.request_timeout client.read_timeout = timeout begin res = client.start do |http| http.request(req) end rescue Timeout::Error res = TimeoutError, "Request timed out after #{timeout} seconds." end case res when Net::HTTPSuccess if res.content_type =~ /[\/+]xml$/ logger.debug("Got XML response: \n#{res.body}") if logger return XmlSimple.xml_in_string(res.body, 'forcearray' => false, 'keeproot' => false ) else logger.debug("Got #{res.content_type.inspect} response: \n#{res.body}") if logger return res.body end when TimeoutError logger.debug(res) if logger return XmlSimple.xml_in_string(res, 'forcearray' => false, 'keeproot' => false ) else $LAST_ERROR_BODY = res.body # FIXME: this is dumb... need a better way of reporting errors $LAST_ERROR_RESPONSE = res # this is currently unused within Restr, but may be useful for debugging logger.error("Got error response '#{res.message}(#{res.code})': #{res.body.blank? ? '(blank response body)' : res.body}") if logger res.error! end end
Generated with the Darkfish Rdoc Generator 2.