class ApiResource::Connection

Class to handle connections to remote web services. This class is used by ActiveResource::Base to interface with REST services.

Constants

HTTP_FORMAT_HEADER_NAMES

Attributes

auth_type[R]
format[RW]
password[R]
proxy[R]
site[R]
ssl_options[R]
timeout[R]
user[R]

Public Class Methods

new(site, format = ApiResource::Formats::JsonFormat) click to toggle source

The site parameter is required and will set the site attribute to the URI for the remote resource service.

# File lib/api_resource/connection.rb, line 32
def initialize(site, format = ApiResource::Formats::JsonFormat)
  raise ArgumentError, 'Missing site URI' unless site
  @user = @password = nil
  @uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
  self.site = site
  self.format = format
end
requests() click to toggle source
# File lib/api_resource/connection.rb, line 25
def requests
  @@requests ||= []
end

Public Instance Methods

delete(path, headers = {}) click to toggle source
# File lib/api_resource/connection.rb, line 56
def delete(path, headers = {})
  request(:delete, path, build_request_headers(headers, :delete, self.site.merge(path)))
  return true
end
get(path, headers = {}) click to toggle source
# File lib/api_resource/connection.rb, line 52
def get(path, headers = {})
  format.decode(request(:get, path, build_request_headers(headers, :get, self.site.merge(path))))
end
head(path, headers = {}) click to toggle source
# File lib/api_resource/connection.rb, line 61
def head(path, headers = {})
  request(:head, path, build_request_headers(headers, :head, self.site.merge(path)))
end
post(path, body = {}, headers = {}) click to toggle source
# File lib/api_resource/connection.rb, line 75
def post(path, body = {}, headers = {})
  if !body.is_a?(String) && RestClient::Payload.has_file?(body)
    format.decode(request(:post, path, body, build_request_headers(headers, :post, self.site.merge(path))))
  else
    format.decode(request(:post, path, body, build_request_headers(headers, :post, self.site.merge(path))))
  end
end
put(path, body = {}, headers = {}) click to toggle source
# File lib/api_resource/connection.rb, line 66
def put(path, body = {}, headers = {})
  # If there's a file to send then we can't use JSON or XML
  if !body.is_a?(String) && RestClient::Payload.has_file?(body)
    format.decode(request(:put, path, body, build_request_headers(headers, :put, self.site.merge(path))))
  else
    format.decode(request(:put, path, body, build_request_headers(headers, :put, self.site.merge(path))))
  end
end
site=(site) click to toggle source

Set URI for remote service.

# File lib/api_resource/connection.rb, line 41
def site=(site)
  @site = site.is_a?(URI) ? site : @uri_parser.parse(site)
  @user = @uri_parser.unescape(@site.user) if @site.user
  @password = @uri_parser.unescape(@site.password) if @site.password
end
timeout=(timeout) click to toggle source

Sets the number of seconds after which HTTP requests to the remote service should time out.

# File lib/api_resource/connection.rb, line 48
def timeout=(timeout)
  @timeout = timeout
end

Private Instance Methods

build_request_headers(headers, verb, uri) click to toggle source
# File lib/api_resource/connection.rb, line 154
def build_request_headers(headers, verb, uri)
  http_format_header(verb).update(headers)
end
handle_response() { || ... } click to toggle source

Handles response and error codes from the remote service.

# File lib/api_resource/connection.rb, line 97
def handle_response(&block)
  begin
    result = yield
  rescue RestClient::RequestTimeout
    raise ApiResource::RequestTimeout.new("Request Time Out")
  rescue Exception => error
    if error.respond_to?(:http_code)
      result = error.response
    else
      raise "Unknown error #{error}"
    end
  end
  return propogate_response_or_error(result, result.code)
end
http(path) click to toggle source

Creates new Net::HTTP instance for communication with the remote service and resources.

# File lib/api_resource/connection.rb, line 147
def http(path)
  unless path =~ /\./
    path += ".#{self.format.extension}"
  end
  RestClient::Resource.new "#{site.scheme}://#{site.host}:#{site.port}#{path}", :timeout => @timeout ? @timeout : 10, :open_timeout => @timeout ? @timeout : 10
end
http_format_header(verb) click to toggle source
# File lib/api_resource/connection.rb, line 158
def http_format_header(verb)
  {HTTP_FORMAT_HEADER_NAMES[verb] => format.mime_type}
end
propogate_response_or_error(response, code) click to toggle source
# File lib/api_resource/connection.rb, line 112
def propogate_response_or_error(response, code)
  case code.to_i
    when 301,302
      raise ApiResource::Redirection.new(response)
    when 200..400
      response.body
    when 400
      raise ApiResource::BadRequest.new(response)
    when 401
      raise ApiResource::UnauthorizedAccess.new(response)
    when 403
      raise ApiResource::ForbiddenAccess.new(response)
    when 404
      raise ApiResource::ResourceNotFound.new(response)
    when 405
      raise ApiResource::MethodNotAllowed.new(response)
    when 406
      raise ApiResource::NotAccepatable.new(response)
    when 409
      raise ApiResource::ResourceNotFound.new(response)
    when 410
      raise ApiResource::ResourceGone.new(response)
    when 422
      raise ApiResource::UnprocessableEntity.new(response)
    when 401..500
      raise ApiResource::ClientError.new(response)
    when 500..600
      raise ApiResource::ServerError.new(response)
    else
      raise ApiResource::ConnectionError.new(response, "Unknown response code: #{code}")
  end
end
request(method, path, *arguments) click to toggle source

Makes a request to the remote service.

# File lib/api_resource/connection.rb, line 86
def request(method, path, *arguments)
  handle_response do
    ActiveSupport::Notifications.instrument("request.api_resource") do |payload|
      payload[:method]      = method
      payload[:request_uri] = "#{site.scheme}://#{site.host}:#{site.port}#{path}"
      payload[:result]      = http(path).send(method, *arguments)
    end
  end
end