# 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 Faraday.new(url: Configuration.base_url, headers: auth_headers, request: { timeout: DEFAULT_TIMEOUT }) do |faraday| faraday.response :raise_error faraday.response :logger, Configuration.logger, bodies: true do |logger| logger.filter(/(Api-Key)([\s:"]*)(.+)(\"{1})/, "[REMOVED]") end faraday.adapter(detect_adapter) 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 # rubocop:disable Metrics/MethodLength 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 # rubocop:enable Metrics/MethodLength end end end end