lib/contextio/api.rb in contextio-1.7.1 vs lib/contextio/api.rb in contextio-1.7.2

- old
+ new

@@ -93,34 +93,22 @@ # request. # # @raise [API::Error] if the response code isn't in the 200 or 300 range. def request(method, resource_path, params = {}) response = oauth_request(method, resource_path, params, { 'Accept' => 'application/json' }) - body = response.body - results = JSON.parse(body.to_s) unless response.body.to_s.empty? - unless response.success? - if results.is_a?(Hash) && results['type'] == 'error' - message = results['value'] - else - message = "HTTP #{response.status} Error" - end - - raise API::Error, message + with_error_handling(response) do |response| + parse_json(response.body) end - - results end def raw_request(method, resource_path, params={}) response = oauth_request(method, resource_path, params) - unless response.success? - raise API::Error, "HTTP #{response.status} Error" + with_error_handling(response) do |response| + response.body end - - response.body end private # Makes a request signed for OAuth, encoding parameters correctly, etc. @@ -182,9 +170,56 @@ faraday.request :oauth, consumer_key: key, consumer_secret: secret faraday.request :url_encoded faraday.adapter Faraday.default_adapter + end + end + + # Errors can come in a few shapes and we want to detect them and extract the + # useful information. If no errors are found, it calls the provided block + # and passes the response through. + # + # @param [Faraday::Response] response A response object from making a request to the + # API with Faraday. + # + # @raise [API::Error] if the response code isn't in the 200 or 300 range. + def with_error_handling(response, &block) + return block.call(response) if response.success? + + parsed_body = parse_json(response.body) + message = determine_best_error_message(parsed_body) || "HTTP #{response.status} Error" + + raise API::Error, message + end + + # Parses JSON if there's valid JSON passed in. + # + # @param [String] document A string you suspect may be a JSON document. + # + # @return [Hash, Array, Nil] Either a parsed version of the JSON document or + # nil, if the document wasn't valid JSON. + def parse_json(document) + return JSON.parse(document.to_s) + rescue JSON::ParserError => e + return nil + end + + # Given a parsed JSON body from an error response, figures out if it can + # pull useful information therefrom. + # + # @param [Hash] parsed_body A Hash parsed from a JSON document that may + # describe an error condition. + # + # @return [String, Nil] If it can, it will return a human-readable + # error-describing String. Otherwise, nil. + def determine_best_error_message(parsed_body) + return unless parsed_body.respond_to?(:[]) + + if parsed_body['type'] == 'error' + return parsed_body['value'] + elsif parsed_body.has_key?('success') && !parsed_body['success'] + return [parsed_body['feedback_code'], parsed_body['connectionLog']].compact.join("\n") end end end end