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