# frozen_string_literal: true module ONEAccess module Http class HttpClient class << self DEFAULT_TIMEOUT = 10 def get(url, params = {}, headers = {}) response = connection.get do |request| request.url(url) request.params.merge!(params) request.headers.merge!(headers) end handle_response(response) rescue Faraday::TimeoutError => e raise create_timeout_error(e, url) rescue Faraday::Error => e raise create_api_error(e) end def post(url, body, headers = {}) response = connection.post do |request| request.url(url) request.headers.merge!(headers) request.body = body.to_json end handle_response(response) rescue Faraday::TimeoutError => e raise create_timeout_error(e, url) rescue Faraday::Error => e raise create_api_error(e) end private def handle_response(response) # make sure we have a valid JSON in the response if response.headers['Content-Type'] == 'application/json' begin MultiJson.load(response.body) rescue MultiJson::ParseError raise Error::APIError.new(500, response.code, "Invalid JSON Response:'#{message.body}'") end end response end def connection parameters = { url: Configuration.base_url, headers: auth_headers, request: { timeout: DEFAULT_TIMEOUT } } Faraday.new(parameters) do |faraday| faraday.response(:raise_error) faraday.adapter(detect_adapter) if Configuration.log_requests faraday.response(:logger, Configuration.logger, bodies: true) do |logger| logger.filter(/(Api-Key)([\s:"]*)(.+)(\"{1})/, '[REMOVED]') end end end end def create_timeout_error(_error, url) Error::APIError.new(408, 408, "Timeout #{DEFAULT_TIMEOUT} at #{url}") end def create_api_error(error) status = error.response[:status] body = error.response[:body] headers = error.response[:headers] if headers['Content-Type'] == 'application/json' handle_json_error(body, status) else Error::APIError.new(status, status, "API Response body:'#{body}'") end end def handle_json_error(body, status) api_error_data = Response::APIError.new Response::Representer::APIError.new(api_error_data).from_json(body) Error::APIError.new( status, api_error_data.api_status_code, api_error_data.api_status_message, ) rescue MultiJson::ParseError Error::APIError.new(500, 500, "Invalid JSON:'#{body}'") end def auth_headers { 'X-One-Access-Api-Key' => Configuration.api_key, 'Authorization' => "X-One-Access-Master-Api-Key #{Configuration.master_api_key}", } end # Auto-detect the best adapter (HTTP "driver") available, based on libraries # loaded by the user, preferring those with persistent connections ("keep-alive") by default def detect_adapter if defined?(::Patron) :patron elsif defined?(::Typhoeus) :typhoeus elsif defined?(::HTTPClient) :httpclient elsif defined?(::Net::HTTP::Persistent) :net_http_persistent else ::Faraday.default_adapter end end end end end end