lib/xeroizer/http.rb in xeroizer-2.20.0 vs lib/xeroizer/http.rb in xeroizer-3.0.0

- old
+ new

@@ -13,11 +13,11 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. module Xeroizer module Http class BadResponse < XeroizerError; end - RequestInfo = Struct.new(:url, :headers, :params, :body) + RequestInfo = Struct.new(:url, :headers, :params, :body, :method) ACCEPT_MIME_MAP = { :pdf => 'application/pdf', :json => 'application/json' } @@ -51,11 +51,11 @@ http_request(client, :put, url, body, extra_params) end private - def http_request(client, method, url, body, params = {}) + def http_request(client, method, url, request_body, params = {}) # headers = {'Accept-Encoding' => 'gzip, deflate'} headers = self.default_headers.merge({ 'charset' => 'utf-8' }) # include the unitdp query string parameter @@ -87,18 +87,18 @@ uri = URI.parse(url) attempts = 0 - request_info = RequestInfo.new(url, headers, params, body) + request_info = RequestInfo.new(url, headers, params, request_body, method) before_request.call(request_info) if before_request begin attempts += 1 logger.info("XeroGateway Request: #{method.to_s.upcase} #{uri.request_uri}") if self.logger - raw_body = params.delete(:raw_body) ? body : {:xml => body} + raw_body = params.delete(:raw_body) ? request_body : {:xml => request_body} response = with_around_request(request_info) do case method when :get then client.get(uri.request_uri, headers) when :post then client.post(uri.request_uri, raw_body, headers) @@ -107,26 +107,11 @@ end log_response(response, uri) after_request.call(request_info, response) if after_request - case response.code.to_i - when 200 - response.plain_body - when 204 - nil - when 400 - handle_error!(response, body) - when 401 - handle_oauth_error!(response) - when 404 - handle_object_not_found!(response, url) - when 503 - handle_oauth_error!(response) - else - handle_unknown_response_error!(response) - end + HttpResponse.from_response(response, request_body, url).body rescue Xeroizer::OAuth::NonceUsed => exception raise if attempts > nonce_used_max_attempts logger.info("Nonce used: " + exception.to_s) if self.logger sleep_for(1) retry @@ -155,69 +140,9 @@ logger.info("XeroGateway Response (#{response.code})") logger.add(response.code.to_i == 200 ? Logger::DEBUG : Logger::INFO) { "#{uri.request_uri}\n== Response Body\n\n#{response.plain_body}\n== End Response Body" } end - end - - def handle_oauth_error!(response) - error_details = CGI.parse(response.plain_body) - description = error_details["oauth_problem_advice"].first - problem = error_details["oauth_problem"].first - - # see http://oauth.pbworks.com/ProblemReporting - # In addition to token_expired and token_rejected, Xero also returns - # 'rate limit exceeded' when more than 60 requests have been made in - # a second. - if problem - case problem - when "token_expired" then raise OAuth::TokenExpired.new(description) - when "token_rejected" then raise OAuth::TokenInvalid.new(description) - when "rate limit exceeded" then raise OAuth::RateLimitExceeded.new(description) - when "consumer_key_unknown" then raise OAuth::ConsumerKeyUnknown.new(description) - when "nonce_used" then raise OAuth::NonceUsed.new(description) - when "organisation offline" then raise OAuth::OrganisationOffline.new(description) - else raise OAuth::UnknownError.new(problem + ':' + description) - end - else - raise OAuth::UnknownError.new("Xero API may be down or the way OAuth errors are provided by Xero may have changed.") - end - end - - def handle_error!(response, request_body) - - raw_response = response.plain_body - - # XeroGenericApplication API Exceptions *claim* to be UTF-16 encoded, but fail REXML/Iconv parsing... - # So let's ignore that :) - raw_response.gsub! '<?xml version="1.0" encoding="utf-16"?>', '' - - # doc = REXML::Document.new(raw_response, :ignore_whitespace_nodes => :all) - doc = Nokogiri::XML(raw_response) - - if doc && doc.root && doc.root.name == "ApiException" - - raise ApiException.new(doc.root.xpath("Type").text, - doc.root.xpath("Message").text, - raw_response, - doc, - request_body) - - else - raise BadResponse.new("Unparseable 400 Response: #{raw_response}") - end - end - - def handle_object_not_found!(response, request_url) - case request_url - when /Invoices/ then raise InvoiceNotFoundError.new("Invoice not found in Xero.") - when /CreditNotes/ then raise CreditNoteNotFoundError.new("Credit Note not found in Xero.") - else raise ObjectNotFound.new(request_url) - end - end - - def handle_unknown_response_error!(response) - raise BadResponse.new("Unknown response code: #{response.code.to_i}") end def sleep_for(seconds = 1) sleep seconds end