Class: RCRest
- Inherits:
-
Object
- Object
- RCRest
- Defined in:
- lib/rc_rest.rb
Overview
Abstract class for implementing REST APIs.
Example
The following methods must be implemented in sublcasses:
initialize
-
Sets @url to the service enpoint.
check_error
-
Checks for errors in the server response.
parse_response
-
Extracts information from the server response.
If you have extra URL paramaters (application id, output type) or need to perform URL customization, override make_url
and make_multipart
.
class FakeService < RCRest
class Error < RCRest::Error; end
def initialize(appid)
@appid = appid
@url = URI.parse 'http://example.com/api/'
end
def check_error(xml)
raise Error, xml.elements['error'].text if xml.elements['error']
end
def make_url(method, params)
params[:appid] = @appid
super method, params
end
def parse_response(xml)
return xml
end
def test(query)
get :test, :q => query
end
end
Defined Under Namespace
Classes: Error
Constant Summary collapse
- VERSION =
You are using this version of RCRest
'2.1.0'
Instance Method Summary collapse
-
#check_error(xml) ⇒ Object
Must extract and raise an error from
xml
, an REXML::Document, if any. -
#expand_params(params) ⇒ Object
:nodoc:.
-
#get(method, params = {}) ⇒ Object
Performs a GET request for method
method
withparams
. -
#initialize ⇒ RCRest
constructor
Web services initializer.
-
#make_multipart(params) ⇒ Object
Creates a multipart form post for the Hash of parameters
params
. -
#make_url(method, params = nil) ⇒ Object
Creates a URI for method
method
and a Hash of parametersparams
. -
#parse_response(xml) ⇒ Object
Must parse results from
xml
, an REXML::Document, into something sensible for the API. -
#post(method, params = {}) ⇒ Object
Performs a POST request for method
method
withparams
. -
#post_multipart(method, params = {}) ⇒ Object
Performs a POST request for method
method
withparams
, submitting a multipart form.
Constructor Details
#initialize ⇒ RCRest
Web services initializer.
Concrete web services implementations must set the url
instance variable which must be a URI.
65 66 67 |
# File 'lib/rc_rest.rb', line 65 def initialize raise NotImplementedError, 'need to implement #intialize and set @url' end |
Instance Method Details
#check_error(xml) ⇒ Object
Must extract and raise an error from xml
, an REXML::Document, if any. Must return if no error could be found.
73 74 75 |
# File 'lib/rc_rest.rb', line 73 def check_error(xml) raise NotImplementedError end |
#expand_params(params) ⇒ Object
:nodoc:
77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/rc_rest.rb', line 77 def (params) # :nodoc: = [] params.each do |k,v| if v.respond_to? :each and not String === v then v.each { |v| << [k, v] } else << [k, v] end end .sort_by { |k,v| [k.to_s, v.to_s] } end |
#get(method, params = {}) ⇒ Object
Performs a GET request for method method
with params
. Calls #parse_response on the concrete class with an REXML::Document instance and returns its result.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/rc_rest.rb', line 96 def get(method, params = {}) url = make_url method, params url.open do |xml| res = REXML::Document.new xml.read check_error res return parse_response(res) end rescue OpenURI::HTTPError => e xml = REXML::Document.new e.io.read check_error xml raise end |
#make_multipart(params) ⇒ Object
Creates a multipart form post for the Hash of parameters params
. Override this then call super if you need to add extra params like an application id, output type, etc.
#make_multipart handles arguments similarly to #make_url.
163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/rc_rest.rb', line 163 def make_multipart(params) boundary = (0...8).map { rand(255).to_s 16 }.join '_' data = (params).map do |key, value| [ "--#{boundary}", "Content-Disposition: form-data; name=\"#{key}\"", nil, value] end data << "--#{boundary}--" return [boundary, data.join("\r\n")] end |
#make_url(method, params = nil) ⇒ Object
Creates a URI for method method
and a Hash of parameters params
. Override this then call super if you need to add extra params like an application id, output type, etc.
If the value of a parameter responds to #each, make_url creates a key-value pair per value in the param.
Examples:
If the URL base is:
http://example.com/api/
then:
make_url nil, :a => '1 2', :b => [4, 3]
creates the URL:
http://example.com/api/?a=1%202&b=3&b=4
and
make_url :method, :a => '1'
creates the URL:
http://example.com/api/method?a=1
142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/rc_rest.rb', line 142 def make_url(method, params = nil) escaped_params = (params).map do |k,v| k = URI.escape(k.to_s).gsub(';', '%3B').gsub('+', '%2B').gsub('&', '%26') v = URI.escape(v.to_s).gsub(';', '%3B').gsub('+', '%2B').gsub('&', '%26') "#{k}=#{v}" end query = escaped_params.join '&' url = @url + "./#{method}" url.query = query return url end |
#parse_response(xml) ⇒ Object
Must parse results from xml
, an REXML::Document, into something sensible for the API.
180 181 182 |
# File 'lib/rc_rest.rb', line 180 def parse_response(xml) raise NotImplementedError end |
#post(method, params = {}) ⇒ Object
Performs a POST request for method method
with params
. Calls #parse_response on the concrete class with an REXML::Document instance and returns its result.
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/rc_rest.rb', line 189 def post(method, params = {}) url = make_url method, params query = url.query url.query = nil req = Net::HTTP::Post.new url.path req.body = query req.content_type = 'application/x-www-form-urlencoded' res = Net::HTTP.start url.host, url.port do |http| http.request req end xml = REXML::Document.new res.body check_error xml return parse_response(xml) rescue Net::HTTPError => e xml = REXML::Document.new e.res.body check_error xml raise end |
#post_multipart(method, params = {}) ⇒ Object
Performs a POST request for method method
with params
, submitting a multipart form. Calls #parse_response on the concrete class with an REXML::Document instance and returns its result.
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/rc_rest.rb', line 218 def post_multipart(method, params = {}) url = make_url method, {} url.query = nil boundary, data = make_multipart params req = Net::HTTP::Post.new url.path req.content_type = "multipart/form-data; boundary=#{boundary}" req.body = data res = Net::HTTP.start url.host, url.port do |http| http.request req end xml = REXML::Document.new res.body check_error xml return parse_response(xml) rescue Net::HTTPError => e xml = REXML::Document.new e.res.body check_error xml raise end |