module Eligible
Constants
- VERSION
Public Class Methods
add_fingerprint(digest)
click to toggle source
# File lib/eligible.rb, line 99 def self.add_fingerprint(digest) $stderr.puts 'The embedded certificate fingerprint was modified. This should only be done if instructed to by eligible support staff' @@fingerprints << digest end
api_base()
click to toggle source
# File lib/eligible.rb, line 71 def self.api_base @@api_base end
api_base=(api_base)
click to toggle source
# File lib/eligible.rb, line 75 def self.api_base=(api_base) @@api_base = api_base end
api_key()
click to toggle source
# File lib/eligible.rb, line 63 def self.api_key @@api_key end
api_key=(api_key)
click to toggle source
# File lib/eligible.rb, line 67 def self.api_key=(api_key) @@api_key = api_key end
api_key?(params)
click to toggle source
# File lib/eligible.rb, line 112 def self.api_key?(params) Util.key?(params, :api_key) end
api_url(url = '')
click to toggle source
# File lib/eligible.rb, line 59 def self.api_url(url = '') @@api_base + url.to_s end
api_version()
click to toggle source
# File lib/eligible.rb, line 91 def self.api_version @@api_version end
api_version=(version)
click to toggle source
# File lib/eligible.rb, line 87 def self.api_version=(version) @@api_version = version end
direct_response?(params)
click to toggle source
# File lib/eligible.rb, line 104 def self.direct_response?(params) params[:format].is_a?(String) && params[:format].downcase == 'x12' end
fingerprints()
click to toggle source
# File lib/eligible.rb, line 95 def self.fingerprints @@fingerprints end
request(method, url, api_key, params = {}, headers = {})
click to toggle source
# File lib/eligible.rb, line 116 def self.request(method, url, api_key, params = {}, headers = {}) session_token = Util.value(params, :session_token) api_key ||= @@api_key unless session_token test = self.test api_key = Util.value(params, :api_key) if api_key?(params) test = Util.value(params, :test) if test_key?(params) fail AuthenticationError, 'No API key provided. (HINT: set your API key using "Eligible.api_key = <API-KEY>".' unless api_key || session_token lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})" debug_info = { bindings_version: Eligible::VERSION, lang: 'ruby', lang_version: lang_version, platform: RUBY_PLATFORM, publisher: 'eligible', uname: uname } # GET requests, parameters on the query string # POST requests, parameters as json in the body url = api_url(url) case method.to_s.downcase.to_sym when :get, :head, :delete url += "?api_key=#{api_key}" if params && params.count > 0 query_string = Util.flatten_params(params).collect { |key, value| "#{key}=#{Util.url_encode(value)}" }.join('&') url += "&#{query_string}" end url += "&test=#{test}" payload = nil else params.merge!('api_key' => api_key, 'test' => test) payload = Util.key?(params, :file) ? params : Eligible::JSON.dump(params) end begin headers = { x_eligible_debuginfo: Eligible::JSON.dump(debug_info) }.merge(headers) rescue => e headers = { x_eligible_client_raw_user_agent: debug_info.inspect, error: "#{e} (#{e.class})" }.merge(headers) end headers = { user_agent: "eligible-ruby/#{Eligible::VERSION}", authorization: "Bearer #{api_key}", content_type: 'application/json' }.merge(headers) headers[:eligible_version] = api_version if api_version opts = { method: method, url: url, headers: headers, open_timeout: 30, payload: payload, timeout: 80, ssl_verify_callback: verify_certificate, ssl_verify_callback_warnings: false } begin response = execute_request(opts) rescue SocketError => e handle_restclient_error(e) rescue NoMethodError => e # Work around RestClient bug raise unless e.message =~ /\WRequestFailed\W/ e = APIConnectionError.new('Unexpected HTTP response code') handle_restclient_error(e) rescue RestClient::ExceptionWithResponse => e err_rcode = e.http_code err_rbody = e.http_body if err_rcode && err_rbody handle_api_error(err_rcode, err_rbody) else handle_restclient_error(e) end rescue RestClient::Exception, Errno::ECONNREFUSED => e handle_restclient_error(e) end rbody = response.body rcode = response.code begin # Would use :symbolize_names => true, but apparently there is # some library out there that makes symbolize_names not work. resp = direct_response?(params) ? rbody : Eligible::JSON.load(rbody) rescue MultiJson::DecodeError raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody) end resp = Util.symbolize_names(resp) return [ resp, api_key ] end
test()
click to toggle source
# File lib/eligible.rb, line 79 def self.test @@test ? 'true' : 'false' end
test=(is_test)
click to toggle source
# File lib/eligible.rb, line 83 def self.test=(is_test) @@test = is_test end
test_key?(params)
click to toggle source
# File lib/eligible.rb, line 108 def self.test_key?(params) Util.key?(params, :test) end
valid_fingerprint?(received)
click to toggle source
# File lib/eligible.rb, line 232 def self.valid_fingerprint?(received) fingerprints.include?(OpenSSL::Digest::SHA1.hexdigest(received.to_der)) end
verify_certificate()
click to toggle source
# File lib/eligible.rb, line 222 def self.verify_certificate lambda do |preverify_ok, certificate_store| return true if test == 'true' return false unless preverify_ok received = certificate_store.chain.first return true unless received.to_der == certificate_store.current_cert.to_der valid_fingerprint?(received) end end
Private Class Methods
api_error(error_msg, rcode, rbody, error_obj)
click to toggle source
# File lib/eligible.rb, line 297 def self.api_error(error_msg, rcode, rbody, error_obj) APIError.new(error_msg, rcode, rbody, error_obj) end
authentication_error(error_msg, rcode, rbody, error_obj)
click to toggle source
# File lib/eligible.rb, line 293 def self.authentication_error(error_msg, rcode, rbody, error_obj) AuthenticationError.new(error_msg, rcode, rbody, error_obj) end
compose_message_from_error(error)
click to toggle source
# File lib/eligible.rb, line 260 def self.compose_message_from_error(error) return error.to_s unless error.is_a?(Hash) result = error[:details] || error[:reject_reason_description] || error return result.to_s end
compose_message_from_errors(errors)
click to toggle source
# File lib/eligible.rb, line 253 def self.compose_message_from_errors(errors) return unless errors.is_a?(Array) return errors.first[:message] if errors.size == 1 return errors.each_with_index.map { |error, index| "#{index + 1}. #{error[:message]}" }.join("\n") end
error_message(error, errors)
click to toggle source
# File lib/eligible.rb, line 246 def self.error_message(error, errors) message = compose_message_from_errors(errors) return message if message return compose_message_from_error(error) end
execute_request(opts)
click to toggle source
# File lib/eligible.rb, line 242 def self.execute_request(opts) RestClient::Request.execute(opts) end
handle_api_error(rcode, rbody)
click to toggle source
# File lib/eligible.rb, line 266 def self.handle_api_error(rcode, rbody) begin error_obj = Util.symbolize_names(Eligible::JSON.load(rbody)) fail EligibleError unless error_obj.keys.any? { |k| [:error, :errors].include? k } error = error_obj[:error] errors = error_obj[:errors] rescue MultiJson::DecodeError, EligibleError raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody) end error_msg = error_message(error, errors) case rcode when 400, 404 then raise invalid_request_error(error_msg, rcode, rbody, error_obj) when 401 raise authentication_error(error_msg, rcode, rbody, error_obj) else raise api_error(error_msg, rcode, rbody, error_obj) end end
handle_restclient_error(e)
click to toggle source
# File lib/eligible.rb, line 301 def self.handle_restclient_error(e) case e when RestClient::ServerBrokeConnection, RestClient::RequestTimeout message = "Could not connect to Eligible (#{@@api_base}). Please check your internet connection and try again." when RestClient::SSLCertificateNotVerified message = "Could not verify Eligible's SSL certificate." when SocketError message = 'Unexpected error communicating when trying to connect to Eligible.' else message = 'Unexpected error communicating with Eligible. If this problem persists, let us know at support@eligible.com.' end fail APIConnectionError, "#{message}\n\n(Network error: #{e.message})" end
invalid_request_error(error_msg, rcode, rbody, error_obj)
click to toggle source
# File lib/eligible.rb, line 289 def self.invalid_request_error(error_msg, rcode, rbody, error_obj) InvalidRequestError.new(error_msg, rcode, rbody, error_obj) end
uname()
click to toggle source
# File lib/eligible.rb, line 238 def self.uname @@uname ||= RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil end