class Parliament::Request::BaseRequest

Base request object, allowing the user to make a request to an API.

@since 0.7.5

@attr_reader [String] base_url the base url of our api. (eg: example.com - without the trailing slash). @attr_reader [Hash] headers the headers being sent in the request. @attr_reader [Hash] query_params any query parameters to be sent in the request.

Constants

CONNECTTIMEOUT
TIMEOUT

Attributes

base_url[RW]
headers[RW]
base_url[R]
headers[R]
query_params[R]

Public Class Methods

new(base_url: nil, headers: nil, builder: nil, decorators: nil) click to toggle source

Creates a new instance of Parliament::Request::BaseRequest.

An interesting note for initialize is that setting base_url on the class, or using the environment variable PARLIAMENT_BASE_URL means you don't need to pass in a base_url. You can pass one anyway to override the environment variable or class parameter. Similarly, headers can be set by either setting the headers on the class, or passing headers in.

@example Setting the base_url on the class

Parliament::Request::BaseRequest.base_url = 'http://example.com'

Parliament::Request::BaseRequest.new.base_url #=> 'http://example.com'

@example Setting the base_url via environment variable

ENV['PARLIAMENT_BASE_URL'] #=> 'http://test.com'

Parliament::Request::BaseRequest.new.base_url #=> 'http://test.com'

@example Setting the base_url via a parameter

Parliament::Request::BaseRequest.base_url #=> nil
ENV['PARLIAMENT_BASE_URL'] #=> nil

Parliament::Request::BaseRequest.new(base_url: 'http://example.com').base_url #=> 'http://example.com'

@example Overriding the base_url via a parameter

ENV['PARLIAMENT_BASE_URL'] #=> 'http://test.com'

Parliament::Request::BaseRequest.new(base_url: 'http://example.com').base_url #=> 'http://example.com'

@example Setting the headers on the class

Parliament::Request::BaseRequest.headers = { 'Accept' => 'Test' }

Parliament::Request::BaseRequest.new.headers #=> '{ 'Accept' => 'Test' }

@example Setting the headers via a parameter

Parliament::Request::BaseRequest.headers #=> nil

Parliament::Request::BaseRequest.new(headers: '{ 'Accept' => 'Test' }).headers #=> { 'Accept' => 'Test' }

@example Overriding the headers via a parameter

Parliament::Request::BaseRequest.headers = { 'Accept' => 'Test' }

Parliament::Request::BaseRequest.new(headers: '{ 'Accept' => 'Test2' }).headers #=> { 'Accept' => 'Test2' }

@param [String] base_url the base url of our api. (expected: example.com - without the trailing slash). @param [Hash] headers the headers being sent in the request. @param [Parliament::Builder] builder the builder to use in order to build a response. @param [Module] decorators the decorator modules to use in order to provide possible alias methods for any objects created by the builder.

# File lib/parliament/request/base_request.rb, line 63
def initialize(base_url: nil, headers: nil, builder: nil, decorators: nil)
  @base_url     = base_url || self.class.base_url
  @headers      = headers || self.class.headers || {}
  @builder      = builder || Parliament::Builder::BaseResponseBuilder
  @decorators   = decorators
  @query_params = {}
end

Public Instance Methods

get(params: nil, timeout: TIMEOUT, connecttimeout: CONNECTTIMEOUT) click to toggle source

Makes an HTTP GET request and process results into a response.

@example HTTP GET request

request = Parliament::Request::BaseRequest.new(base_url: 'http://example.com/people/123')

# url: http://example.com/people/123

response = request.get #=> #<Parliament::Response::BaseResponse ...>

@example HTTP GET request with URI encoded form values

request = Parliament::Request.new(base_url: 'http://example.com/people/current')

# url: http://example.com/people/current?limit=10&page=4&lang=en-gb

response = request.get({ limit: 10, page: 4, lang: 'en-gb' }) #=> #<Parliament::Response::BaseResponse ...>

@raise [Parliament::ServerError] when the server responds with a 5xx status code. @raise [Parliament::ClientError] when the server responds with a 4xx status code. @raise [Parliament::NoContentResponseError] when the response body is empty.

@param [Hash] params (optional) additional URI encoded form values to be added to the URI. @param [Integer] timeout (optional) time limit for the entire request in seconds. @param [Integer] connecttimeout (optional) time limit for just the connection in seconds.

@return [Parliament::Response::BaseResponse] a Parliament::Response::BaseResponse object containing all of the data returned from the URL.

# File lib/parliament/request/base_request.rb, line 96
def get(params: nil, timeout: TIMEOUT, connecttimeout: CONNECTTIMEOUT)
  Typhoeus::Config.user_agent = 'Ruby'

  uri_hash = separate_uri(query_url, @query_params, params)

  typhoeus_request = Typhoeus::Request.new(
    uri_hash[:endpoint],
    method:          :get,
    params:          uri_hash[:params],
    headers:         headers,
    timeout:         timeout,
    connecttimeout:  connecttimeout,
    accept_encoding: 'gzip'
  )

  response = typhoeus_request.run

  handle_errors(response)

  build_response(response)
end
post(params: nil, body: nil, timeout: TIMEOUT, connecttimeout: CONNECTTIMEOUT) click to toggle source

Makes an HTTP POST request and process results into a response.

@example HTTP POST request

request = Parliament::Request::BaseRequest.new(base_url: 'http://example.com/people/123', headers: {'Content': 'application/json', 'Accept': 'application/json'})

# url: http://example.com/people/123

response = request.post(body: {}.to_json) #=> #<Parliament::Response::BaseResponse ...>

@example HTTP POST request with URI encoded form values

request = Parliament::Request::BaseRequest.new(base_url: 'http://example.com/people/current', headers: {'Content': 'application/json', 'Accept': 'application/json'})

# url: http://example.com/people/current?limit=10&page=4&lang=en-gb

response = request.post({ limit: 10, page: 4, lang: 'en-gb' }, body: {}.to_json) #=> #<Parliament::Response::BaseResponse ...>

@raise [Parliament::ServerError] when the server responds with a 5xx status code. @raise [Parliament::ClientError] when the server responds with a 4xx status code. @raise [Parliament::NoContentResponseError] when the response body is empty.

@param [Hash] params (optional) additional URI encoded form values to be added to the URI. @param [String] body (optional) body of the post request. @param [Integer] timeout (optional) time limit for the entire request in seconds. @param [Integer] connecttimeout (optional) time limit for just the connection in seconds.

@return [Parliament::Response::BaseResponse] a Parliament::Response::BaseResponse object containing all of the data returned from the URL.

# File lib/parliament/request/base_request.rb, line 144
def post(params: nil, body: nil, timeout: TIMEOUT, connecttimeout: CONNECTTIMEOUT)
  Typhoeus::Config.user_agent = 'Ruby'

  uri_hash = separate_uri(query_url, @query_params, params)

  typhoeus_request = Typhoeus::Request.new(
    uri_hash[:endpoint],
    method:          :post,
    params:          uri_hash[:params],
    headers:         headers.merge({ 'Content-Type' => 'application/json' }),
    accept_encoding: 'gzip',
    timeout:         timeout,
    connecttimeout:  connecttimeout,
    body:            body
  )

  response = typhoeus_request.run

  handle_errors(response)

  build_response(response)
end

Private Instance Methods

build_response(response) click to toggle source
# File lib/parliament/request/base_request.rb, line 175
def build_response(response)
  @builder.new(response: response, decorators: @decorators).build
end
default_headers() click to toggle source
# File lib/parliament/request/base_request.rb, line 183
def default_headers
  { 'Accept' => ['*/*', 'application/n-triples'] }
end
handle_errors(response) click to toggle source
# File lib/parliament/request/base_request.rb, line 191
def handle_errors(response)
  exception_class = if response.success? # 2xx Status
                      Parliament::NoContentResponseError if response.headers&.[]('Content-Length') == '0' ||
                                                            (response.headers&.[]('Content-Length').nil? && response.body.empty?)
                    elsif /\A4\w{2}/.match(response.code.to_s) # 4xx Status
                      Parliament::ClientError
                    elsif /\A5\w{2}/.match(response.code.to_s) # 5xx Status
                      Parliament::ServerError
                    end

  raise exception_class.new(query_url, response) if exception_class
end
query_url() click to toggle source
# File lib/parliament/request/base_request.rb, line 179
def query_url
  @base_url
end
separate_uri(query_url, query_params, additional_params) click to toggle source
# File lib/parliament/request/base_request.rb, line 204
def separate_uri(query_url, query_params, additional_params)
  endpoint = URI.parse(query_url)

  temp_params = {}

  if endpoint.query
    # Returns [ ["key", "value"], ["key", "value"] ]
    key_value_array = URI.decode_www_form(endpoint.query)
    key_value_array.map! { |key_value_pair| [key_value_pair[0].to_sym, key_value_pair[1]] }
    temp_params = key_value_array.to_h
  end

  temp_params = temp_params.merge(query_params)
  temp_params = temp_params.merge(additional_params) unless additional_params.nil?

  endpoint.query = nil

  { endpoint: endpoint, params: temp_params }
end