class BillForward::Client
Attributes
all_verbs[RW]
default_client[R]
default client is a singleton client
api_token[RW]
host[RW]
logger[RW]
use_logging[RW]
Public Class Methods
default_client=(default_client)
click to toggle source
# File lib/bill_forward/client.rb, line 59 def default_client=(default_client) if (default_client == nil) # meaningless, but required for resetting this class after a test run @default_client = nil return end TypeCheck.verifyObj(Client, default_client, 'default_client') @default_client = default_client end
make_default_client(options)
click to toggle source
Constructs a client, and sets it to be used as the default client. @param options={} [Hash] Options with which to construct client
@return [Client] The constructed client
# File lib/bill_forward/client.rb, line 83 def self.make_default_client(options) constructedClient = self.new(options) self.default_client = constructedClient end
new(options={})
click to toggle source
# File lib/bill_forward/client.rb, line 88 def initialize(options={}) TypeCheck.verifyObj(Hash, options, 'options') @use_logging = options[:use_logging] @logger = options[:logger] || Logger.new(STDOUT) if options[:host] @host = options[:host] else raise ClientInstantiationException.new "Failed to initialize BillForward API Client\n" + "Required parameters: :host and either [:api_token] or all of [:client_id, :client_secret, :username, :password].\n" + "Supplied Parameters: #{options}" end if options[:use_proxy] @use_proxy = options[:use_proxy] @proxy_url = options[:proxy_url] end if options[:api_token] @api_token = options[:api_token] else @api_token = nil if options[:client_id] and options[:client_secret] and options[:username] and options[:password] @client_id = options[:client_id] @client_secret = options[:client_secret] @username = options[:username] @password = options[:password] else raise ClientException.new "Failed to initialize BillForward API Client\n"+ "Required parameters: :host and either [:api_token] or all of [:client_id, :client_secret, :username, :password].\n" + "Supplied Parameters: #{options}" end end @authorization = nil end
Public Instance Methods
execute_request(verb, url, token, payload=nil)
click to toggle source
# File lib/bill_forward/client.rb, line 125 def execute_request(verb, url, token, payload=nil) # Enable Fiddler: if @use_proxy RestClient.proxy = @proxy_url end # content_type seems to be broken on generic execute. # darn. # RestClient::Request.execute(options) options = { :Authorization => "Bearer #{token}", :accept => 'application/json' } haspayload = @@payload_verbs.include?(verb) if (haspayload) options.update(:content_type => 'application/json') end args = [url, options] args.insert(1, payload) if haspayload log "#{verb.upcase} #{url}" log "headers: #{JSON.pretty_generate(options)}" log "payload: #{payload}" if haspayload RestClient.send(verb.intern, *args) end
Private Instance Methods
get_token()
click to toggle source
# File lib/bill_forward/client.rb, line 319 def get_token if @api_token @api_token else if @authorization and Time.now < @authorization["expires_at"] return @authorization["access_token"] end begin response = RestClient.get("#{@host}oauth/token", :params => { :username => @username, :password => @password, :client_id => @client_id, :client_secret => @client_secret, :grant_type => "password" }, :accept => :json) @authorization = JSON.parse(response.to_str) @authorization["expires_at"] = Time.now + @authorization["expires_in"] @authorization["access_token"] rescue => e if e.respond_to? "response" log "BILL FORWARD CLIENT ERROR", e.response else log "BILL FORWARD CLIENT ERROR", e, e.to_json end nil end end end
handle_api_error(rcode, rbody)
click to toggle source
# File lib/bill_forward/client.rb, line 277 def handle_api_error(rcode, rbody) begin # Example error JSON: # { # "errorType" : "ValidationError", # "errorMessage" : "Validation Error - Entity: Subscription Field: type Value: null Message: may not be null\nValidation Error - Entity: Subscription Field: productID Value: null Message: may not be null\nValidation Error - Entity: Subscription Field: name Value: null Message: may not be null\n", # "errorParameters" : [ "type", "productID", "name" ] # } error = JSON.parse(rbody) errorType = error['errorType'] errorMessage = error['errorMessage'] if (error.key? 'errorParameters') errorParameters = error['errorParameters'] raise_message = "\n====\n#{rcode} API Error.\nType: #{errorType}\nMessage: #{errorMessage}\nParameters: #{errorParameters}\n====\n" else if (errorType == 'Oauth') split = errorMessage.split(', ') error = split.first.split('=').last description = split.last.split('=').last raise_message = "\n====\n#{rcode} Authorization failed.\nType: #{errorType}\nError: #{error}\nDescription: #{description}\n====\n" raise ApiAuthorizationError.new(error, rbody), raise_message else raise_message = "\n====\n#{rcode} API Error.\nType: #{errorType}\nMessage: #{errorMessage}\n====\n" end end raise ApiError.new(error, rbody), raise_message end raise_message = "\n====\n#{rcode} API Error.\n Response body: #{rbody}\n====\n" raise ApiError.new(nil, rbody), raise_message end
handle_restclient_error(e)
click to toggle source
# File lib/bill_forward/client.rb, line 258 def handle_restclient_error(e) connection_message = "Please check your internet connection and try again. " case e when RestClient::RequestTimeout message = "Could not connect to BillForward (#{@host}). #{connection_message}" when RestClient::ServerBrokeConnection message = "The connection to the server (#{@host}) broke before the " \ "request completed. #{connection_message}" when SocketError message = "Unexpected error communicating when trying to connect to BillForward. " \ "Please confirm that (#{@host}) is a BillForward API URL. " else message = "Unexpected error communicating with BillForward. " end raise ClientException.new(message + "\n\n(Network error: #{e.message})") end
log(*args)
click to toggle source
# File lib/bill_forward/client.rb, line 315 def log(*args) @logger.info *args if @use_logging end
request(verb, url, params={}, payload=nil)
click to toggle source
# File lib/bill_forward/client.rb, line 207 def request(verb, url, params={}, payload=nil) qualified_url = "#{@host}#{url}" split = qualified_url.split('?') distilled_url = split.first override_params = split.length > 1 \ ? split[1] \ : '' param_string = override_params.empty? \ ? ((params && params.any?) \ ? uri_encode(params) \ : '') \ : override_params # Make params into query parameters full_url = param_string.empty? \ ? distilled_url \ : [distilled_url, param_string].join('?') token = get_token begin response = execute_request(verb, full_url, token, payload) parsed = JSON.parse(response.to_str) pretty = JSON.pretty_generate(parsed) log "response: \n#{pretty}" return parsed rescue SocketError => e handle_restclient_error(e) rescue NoMethodError => e # Work around RestClient bug if e.message =~ /\WRequestFailed\W/ e = APIConnectionError.new('Unexpected HTTP response code') handle_restclient_error(e) else raise end rescue RestClient::ExceptionWithResponse => e if rcode = e.http_code and rbody = e.http_body handle_api_error(rcode, rbody) else handle_restclient_error(e) end rescue RestClient::Exception, Errno::ECONNREFUSED => e handle_restclient_error(e) end end
uri_encode(params = {})
click to toggle source
# File lib/bill_forward/client.rb, line 195 def uri_encode(params = {}) TypeCheck.verifyObj(Hash, params, 'params') encoded_params = params.reduce([]) do |accumulator, (iterand_key, iterand_value)| encoded_key = ERB::Util.url_encode iterand_key encoded_value = ERB::Util.url_encode iterand_value accumulator + ["#{encoded_key}=#{encoded_value}"] end query = encoded_params.join '&' end