lib/oneaccess/http/http_client.rb in oneaccess-1.0.0 vs lib/oneaccess/http/http_client.rb in oneaccess-1.0.1

- old
+ new

@@ -2,35 +2,114 @@ module ONEAccess module Http class HttpClient class << self - def get(url, params = {}) - RestClient.get(url, { params: params }.merge(auth_headers)) - rescue RestClient::Exception => e + 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 = {}) - RestClient.post(url, body.to_json, headers.merge(auth_headers)) - rescue RestClient::Exception => e + 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(error.http_body) - Error::APIError.new(error.http_code, api_error_data.api_status_code, api_error_data.api_status_message) + 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