class Shippo::API::Request

This class is the primary internal Interface to the Shippo API.

Public consumers should use Model API, and perform actions on models rather than submit requests directly using this class.

Request instance is created with the intention to execute a single API call and once executed, it stores response object. Used requests can not be re-executed.

Example

@request = Shippo::API::Request.new(
         method: :get,
            uri: '/address,
         params: { object_id: 1 },
        headers: { 'Last-Modified' => '1213145' }
begin
  @response = @request.execute
  Shippo::Address.from(@response)
# =>

Attributes

headers[RW]
method[RW]
params[RW]
parsed_response[RW]

Result of the execute method is stored in response and parsed_response

password[RW]
redirection_history[RW]

Result of the execute method is stored in response and parsed_response

response[RW]

Result of the execute method is stored in response and parsed_response

url[RW]
username[RW]

Public Class Methods

new(method:, uri:, params: {}, headers: {}) click to toggle source

@param [symbol] method :get or any other method such as :put, :post, etc. @param [String] uri URI component appended to the base URL @param [Hash] params parameters to append to the URL @param [Hash] headers headers hash sent to the server

# File lib/shippo/api/request.rb, line 44
def initialize(method:, uri:, params: {}, headers: {})
  self.method   = method
  self.params   = params
  self.headers  = headers
  self.url      = api_url(uri)
  self.response = nil
end

Public Instance Methods

execute() click to toggle source
# File lib/shippo/api/request.rb, line 52
def execute
  raise ArgumentError.new('Response is already defined, create another Request object.') if self.response
  validate!
  begin
    self.response        = shippo_phone_home
    self.parsed_response = JSON::parse(response.body, { symbolize_names: true })

  rescue ::RestClient::Unauthorized => e
    raise Shippo::Exceptions::AuthenticationError.new(e.message)

  rescue ::RestClient::BadRequest => e
    if e.respond_to?(:response) && e.response.is_a?(RestClient::Response)
      awesome_print_response(e) if Shippo::API.debug?
      raise Shippo::Exceptions::APIServerError.new('Backend responded with an error',
                                                   self, e.response, e.message)
    end

  rescue ::JSON::JSONError, ::JSON::ParserError => e
    raise Shippo::Exceptions::InvalidJsonError.new(e.message)

  rescue ::RestClient::BadRequest => e
    raise Shippo::Exceptions::InvalidInputError.new(e.inspect)

  rescue ::RestClient::Exception => e
    raise Shippo::Exceptions::ConnectionError.new(connection_error_message(url, e))

  rescue StandardError => e
    raise Shippo::Exceptions::ConnectionError.new(connection_error_message(url, e)) if e.message =~ /TCP|connection|getaddrinfo/

    STDERR.puts "#{self.class.name}: Internal error occurred while connecting to #{url}: #{e.message}"
    STDERR.puts 'Stack Trace'
    STDERR.puts e.backtrace.join("\n")
    raise Shippo::Exceptions::Error.new(e)
  end
  self.parsed_response
end

Private Instance Methods

api_url(uri_component = '') click to toggle source
# File lib/shippo/api/request.rb, line 173
def api_url(uri_component = '')
  base + uri_component
end
awesome_print_response(e) click to toggle source
# File lib/shippo/api/request.rb, line 139
def awesome_print_response(e)
  begin
    h = JSON.parse(e.response)
    if h
      puts "\nSERVER RESPONSE:"
      ap JSON.parse(e.response)
    end
  rescue nil
  end
end
base() click to toggle source
# File lib/shippo/api/request.rb, line 150
def base
  ::Shippo::API.base
end
connection_error_message(url, error) click to toggle source
# File lib/shippo/api/request.rb, line 162
      def connection_error_message(url, error)
        %Q[Could not connect to the Shippo API, via URL
  #{url}.

Please check your Internet connection, try again, if the problem
persists please contact Shippo Customer Support.

Error Description:
  #{error.class.name} ⇨ #{error.message}].gsub(/^\s*/, '')
      end
make_opts!(headers, method, payload, url) click to toggle source
# File lib/shippo/api/request.rb, line 116
def make_opts!(headers, method, payload, url)
  { :headers      => headers,
    :method       => method,
    :payload      => payload,
    :url          => url,
    :open_timeout => ::Shippo::API.open_timeout,
    :timeout      => ::Shippo::API.read_timeout,
    :user         => username,
    :password     => password,
    :user_agent   => 'Shippo/v2.0 RubyBindings'
  }
end
make_request!(opts) click to toggle source
# File lib/shippo/api/request.rb, line 106
def make_request!(opts)
  RestClient::Request.execute(opts) { |response, &block|
    if [301, 302, 307].include? response.code
      response.follow_redirection(&block)
    else
      response.return!(&block)
    end
  }
end
params_to_url(params, url) click to toggle source
# File lib/shippo/api/request.rb, line 177
def params_to_url(params, url)
  pairs = []
  params.each { |k, v|
    pairs.push "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"
  }
  url += "?#{pairs.join('&')}" unless pairs.empty?
  url
end
setup_headers!(headers) click to toggle source
# File lib/shippo/api/request.rb, line 129
def setup_headers!(headers)
  additional_hash = {
    :accept        => :json,
    :content_type  => :json,
    :Authorization => "ShippoToken #{token}"
  }
  additional_hash[:'Shippo-API-Version'] = version if version
  headers.merge!(additional_hash)
end
shippo_phone_home() click to toggle source
# File lib/shippo/api/request.rb, line 91
def shippo_phone_home
  payload     = nil
  request_url = url
  (method == :get) ? request_url = params_to_url(params, url) : payload = params.to_json
  setup_headers!(headers)
  opts = make_opts!(headers, method, payload, request_url)

  if Shippo::API.debug?
    puts "\nCLIENT REQUEST:"
    ap opts
  end

  make_request!(opts)
end
token() click to toggle source
# File lib/shippo/api/request.rb, line 154
def token
  ::Shippo::API.token
end
validate!() click to toggle source
# File lib/shippo/api/request.rb, line 186
def validate!
  raise Shippo::Exceptions::AuthenticationError.new(
    'API credentials seems to be missing, perhaps you forgot to set Shippo::API.token?') \
    unless token
end
version() click to toggle source
# File lib/shippo/api/request.rb, line 158
def version
  ::Shippo::API.version
end