lib/xero_gateway/http.rb in xero_gateway-float-2.0.18 vs lib/xero_gateway/http.rb in xero_gateway-float-2.1.1

- old
+ new

@@ -5,31 +5,33 @@ ROOT_CA_FILE = File.join(File.dirname(__FILE__), 'ca-certificates.crt') unless defined? ROOT_CA_FILE def log(str) XeroGateway.log("HTTP : "+str) end - def http_get(client, url, extra_params = {}) + + def http_get(client, url, extra_params = {}, headers = {}) log "get | #{url} :: #{extra_params.inspect}" - http_request(client, :get, url, nil, extra_params) + http_request(client, :get, url, nil, extra_params, headers) end - def http_post(client, url, body, extra_params = {}) + def http_post(client, url, body, extra_params = {}, headers = {}) log "post | #{url} :: #{extra_params.inspect}" - http_request(client, :post, url, body, extra_params) + http_request(client, :post, url, body, extra_params, headers) end - def http_put(client, url, body, extra_params = {}) + def http_put(client, url, body, extra_params = {}, headers = {}) log "put | #{url} :: #{extra_params.inspect}" - http_request(client, :put, url, body, extra_params) + http_request(client, :put, url, body, extra_params, headers) end private - - def http_request(client, method, url, body, params = {}) + + def http_request(client, method, url, body, params = {}, headers = {}) # headers = {'Accept-Encoding' => 'gzip, deflate'} - headers = { 'charset' => 'utf-8' } + headers = headers.merge!('charset' => 'utf-8') + if method != :get headers['Content-Type'] ||= "application/x-www-form-urlencoded" end headers['Accept'] = params.delete(:accept_type) if params[:accept_type] @@ -43,58 +45,62 @@ uri = URI.parse(url) # # Only setup @cached_http once on first use as loading the CA file is quite expensive computationally. # unless @cached_http && @cached_http.address == uri.host && @cached_http.port == uri.port - # @cached_http = Net::HTTP.new(uri.host, uri.port) + # @cached_http = Net::HTTP.new(uri.host, uri.port) # @cached_http.open_timeout = OPEN_TIMEOUT # @cached_http.read_timeout = READ_TIMEOUT # @cached_http.use_ssl = true - # + # # # Need to validate server's certificate against root certificate authority to prevent man-in-the-middle attacks. # @cached_http.ca_file = ROOT_CA_FILE # # http.verify_mode = OpenSSL::SSL::VERIFY_NONE # @cached_http.verify_mode = OpenSSL::SSL::VERIFY_PEER # @cached_http.verify_depth = 5 # end - + logger.info("\n== [#{Time.now.to_s}] XeroGateway Request: #{uri.request_uri} ") if self.logger - + response = case method when :get then client.get(uri.request_uri, headers) when :post then client.post(uri.request_uri, { :xml => body }, headers) when :put then client.put(uri.request_uri, { :xml => body }, headers) end - + if self.logger logger.info("== [#{Time.now.to_s}] XeroGateway Response (#{response.code})") - + unless response.code.to_i == 200 logger.info("== #{uri.request_uri} Response Body \n\n #{response.plain_body} \n == End Response Body") end end - + case response.code.to_i when 200 - response.plain_body + if RUBY_VERSION >= "1.9" + response.plain_body.force_encoding("UTF-8") + else + response.plain_body + end when 400 - handle_error!(body, response) + handle_error!(body, response) when 401 handle_oauth_error!(response) when 404 handle_object_not_found!(response, url) when 503 handle_oauth_error!(response) else raise "Unknown response code: #{response.code.to_i}" end end - + def handle_oauth_error!(response) error_details = CGI.parse(response.plain_body) description = error_details["oauth_problem_advice"].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. case (error_details["oauth_problem"].first) @@ -103,42 +109,42 @@ when "token_rejected" then raise OAuth::TokenInvalid.new(description) when "rate limit exceeded" then raise OAuth::RateLimitExceeded.new(description) else raise OAuth::UnknownError.new(error_details["oauth_problem"].first + ':' + description) end end - + def handle_error!(request_xml, response) - + raw_response = response.plain_body - + # Xero Gateway 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) - + if doc.root.name == "ApiException" - raise ApiException.new(doc.root.elements["Type"].text, + raise ApiException.new(doc.root.elements["Type"].text, doc.root.elements["Message"].text, - request_xml, + request_xml, raw_response) else - + raise "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 /BankTransactions/ then raise BankTransactionNotFoundError.new("Bank Transaction not found in Xero.") when /CreditNotes/ then raise CreditNoteNotFoundError.new("Credit Note not found in Xero.") else raise ObjectNotFound.new(request_url) end end - + end end