class Ecertic::Client
Attributes
apikey[RW]
connection[RW]
secret[RW]
user_agent[RW]
Public Class Methods
default_connection()
click to toggle source
# File lib/ecertic/client.rb, line 17 def self.default_connection Thread.current[:ecertic_client_default_connection] ||= begin Faraday.new do |builder| builder.use Faraday::Response::RaiseError builder.response :json, content_type: /\bjson$/, preserve_raw: true, parser_options: { symbolize_names: true } builder.adapter :net_http_persistent end end end
new(options = {})
click to toggle source
# File lib/ecertic/client.rb, line 8 def initialize(options = {}) defaults = Ecertic::Default.options Ecertic::Default.keys.each do |key| instance_variable_set(:"@#{key}", options[key] || defaults[key]) end @connection = connection || self.class.default_connection @services = {} end
Public Instance Methods
base_url()
click to toggle source
# File lib/ecertic/client.rb, line 29 def base_url @base_url.chomp("/") end
execute(method, path, data = nil, options = {})
click to toggle source
# File lib/ecertic/client.rb, line 41 def execute(method, path, data = nil, options = {}) request(method, path, data, options) end
get(path, options = {})
click to toggle source
# File lib/ecertic/client.rb, line 33 def get(path, options = {}) execute :get, path, nil, options.to_h end
post(path, data = nil, options = {})
click to toggle source
# File lib/ecertic/client.rb, line 37 def post(path, data = nil, options = {}) execute :post, path, data, options end
request(method, path, data = nil, options = {})
click to toggle source
# File lib/ecertic/client.rb, line 45 def request(method, path, data = nil, options = {}) request_options = request_options(method, options, data) uri = "#{base_url}#{path}" begin request_start = Time.now log_request(method, path, request_options[:body], request_options[:headers]) response = connection.run_request(method, uri, request_options[:body], request_options[:headers]) do |req| # req.options.open_timeout = Ecertic.open_timeout # req.options.timeout = Ecertic.read_timeout end log_response(request_start, method, path, response.status, response.body) response rescue StandardError => e log_response_error(request_start, e, method, path) case e when Faraday::ClientError if e.response handle_error_response(e.response) else handle_network_error(e) end else raise end end Ecertic::Response.from_faraday_response(response) end
Private Instance Methods
add_auth_options!(method, options, data)
click to toggle source
# File lib/ecertic/client.rb, line 151 def add_auth_options!(method, options, data) timestamp = (Time.now.to_f * 1000).to_i.to_s hmac = hmac(method, timestamp, options[:body], options[:headers]["Content-Type"]) options[:headers]["Date"] = timestamp options[:headers]["Authorization"] = "Hmac #{apikey}:#{hmac}" end
add_body!(options, data)
click to toggle source
# File lib/ecertic/client.rb, line 146 def add_body!(options, data) options[:headers]["Content-Type"] = content_type(options[:headers]) options[:body] = content_data(options[:headers], data) end
base_options()
click to toggle source
# File lib/ecertic/client.rb, line 130 def base_options { headers: { "Accept" => "application/json", "User-Agent" => format_user_agent, }, } end
content_data(headers, data)
click to toggle source
# File lib/ecertic/client.rb, line 176 def content_data(headers, data) headers["Content-Type"] == "application/json" ? data.to_json : data end
content_type(headers)
click to toggle source
# File lib/ecertic/client.rb, line 172 def content_type(headers) headers["Content-Type"] || "application/json" end
format_user_agent()
click to toggle source
# File lib/ecertic/client.rb, line 164 def format_user_agent if user_agent.to_s.empty? Ecertic::Default::USER_AGENT else "#{Ecertic::Default::USER_AGENT} #{user_agent}" end end
general_api_error(status, body)
click to toggle source
# File lib/ecertic/client.rb, line 110 def general_api_error(status, body) APIError.new("Invalid response object from API: #{body.inspect} " \ "(HTTP response code was #{status})", http_status: status, http_body: body) end
handle_error_response(http_response)
click to toggle source
# File lib/ecertic/client.rb, line 100 def handle_error_response(http_response) begin response = Ecertic::Response.new(http_response) rescue JSON::ParserError raise general_api_error(http_response[:status], http_response[:body]) end raise specific_api_error(response) end
handle_network_error(error)
click to toggle source
# File lib/ecertic/client.rb, line 74 def handle_network_error(error) Ecertic::Utils.log_error("Ecertic network error", error_message: error.message) message = case error when Faraday::ConnectionFailed "Unexpected error communicating when trying to connect to " \ "Ecertic. You may be seeing this message because your DNS is not " \ "working. To check, try running `host http://api.otpsecure.net` from the " \ "command line." when Faraday::SSLError "Could not establish a secure connection to Ecertic, you " \ "may need to upgrade your OpenSSL version. To check, try running " \ "`openssl s_client -connect api.otpsecure.net:443` from the command " \ "line." when Faraday::TimeoutError "Could not connect to Ecertic (#{ Ecertic.api_base}). " \ "Please check your internet connection and try again." else "Unexpected error communicating with Ecertic." end raise APIConnectionError, message + "\n\n(Network error: #{error.message})" end
hmac(method, timestamp, data, content_type)
click to toggle source
# File lib/ecertic/client.rb, line 158 def hmac(method, timestamp, data, content_type) md5 = Digest::MD5.hexdigest(data) signature = "#{method.upcase}\n#{md5}\n#{content_type}\n#{timestamp}" OpenSSL::HMAC.hexdigest("SHA1", secret, signature) end
log_request(method, path, body, headers)
click to toggle source
# File lib/ecertic/client.rb, line 180 def log_request(method, path, body, headers) Ecertic::Utils.log_info("Request to Ecertic API", method: method, path: path) Ecertic::Utils.log_debug("Request details", body: body, headers: headers) end
log_response(request_start, method, path, status, body)
click to toggle source
# File lib/ecertic/client.rb, line 185 def log_response(request_start, method, path, status, body) Ecertic::Utils.log_info("Response from Ecertic API", elapsed: Time.now - request_start, method: method, path: path, status: status) Ecertic::Utils.log_debug("Response details", body: body) end
log_response_error(request_start, error, method, path)
click to toggle source
# File lib/ecertic/client.rb, line 194 def log_response_error(request_start, error, method, path) Ecertic::Utils.log_error("Request error", elapsed: Time.now - request_start, error_message: error.message, method: method, path: path) end
request_options(method, options = {}, data = nil)
click to toggle source
# File lib/ecertic/client.rb, line 139 def request_options(method, options = {}, data = nil) base_options.tap do |options| add_body!(options, data) if data add_auth_options!(method, options, data) if data end end
specific_api_error(response)
click to toggle source
# File lib/ecertic/client.rb, line 116 def specific_api_error(response) Ecertic::Utils.log_error("Ecertic API error", status: response.status) error = case response.status when 400, 404 InvalidRequestError when 401 AuthenticationError else APIError end error.new(response.body, response: response) end