class Vidispine::API::Client::HTTPClient

Constants

DEFAULT_BASE_PATH
DEFAULT_HEADER_ACCEPTS
DEFAULT_HEADER_CONTENT_TYPE
DEFAULT_HTTP_HOST_ADDRESS
DEFAULT_HTTP_HOST_PORT
DEFAULT_PASSWORD
DEFAULT_USERNAME

Attributes

authorization_header_key[RW]
authorization_header_value[RW]
base_uri[RW]
default_base_path[RW]
default_query_data[RW]
default_request_headers[RW]
http[RW]
http_host_address[RW]
http_host_port[RW]
log_pretty_print_body[RW]
log_request_body[RW]
log_response_body[RW]
logger[RW]
password[RW]
request[RW]
response[RW]
use_exceptions[RW]
username[RW]

Public Class Methods

new(args = { }) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 33
def initialize(args = { })
  args = args.dup

  @use_exceptions = args.fetch(:use_exceptions, true)

  initialize_logger(args)
  initialize_http(args)

  logger.debug { "#{self.class.name}::#{__method__} Arguments: #{args.inspect}" }

  @base_uri = args[:base_uri] || "http#{http.use_ssl? ? 's' : ''}://#{http.address}:#{http.port}"
  @default_base_path = args.fetch(:default_base_path, DEFAULT_BASE_PATH)

  @default_query_data = args[:default_query_data] || { }

  @username = args[:username] || DEFAULT_USERNAME
  @password = args[:password] || DEFAULT_PASSWORD

  @authorization_header_key = args.fetch(:authorization_header_key, 'Authorization')
  @authorization_header_value = args.fetch(:authorization_header_value, %(Basic #{["#{username}:#{password}"].pack('m').delete("\r\n")}))

  user_agent = args.fetch(:user_agent, false)
  content_type = args.fetch(:content_type_header, DEFAULT_HEADER_CONTENT_TYPE)
  accept_header = args.fetch(:accept_header, args.fetch(:accepts_header, DEFAULT_HEADER_ACCEPTS))

  @default_request_headers = { }
  @default_request_headers['Content-Type'] = content_type if content_type
  @default_request_headers['Accept'] = accept_header if accept_header
  @default_request_headers[@authorization_header_key] = @authorization_header_value if @authorization_header_key
  @default_request_headers['User-Agent'] = user_agent if user_agent

  @log_request_body = args.fetch(:log_request_body, true)
  @log_response_body = args.fetch(:log_response_body, true)
  @log_pretty_print_body = args.fetch(:log_pretty_print_body, true)

  @parse_response = args.fetch(:parse_response, true)
end

Public Instance Methods

build_and_send_request(method_name = :get, args = { }, options = { }) click to toggle source

First builds and then sends the HTTP request

@param [Symbol] method_name (:get) @param [Hash] args @option args [Hash] :headers ({}) @option args [String] :path ('') @option args [Hash] :query ({}) @option args [Any] :body (nil)

@param [Hash] options @option options [Hash] :default_request_headers (@default_request_headers)

# File lib/vidispine/api/client/http_client.rb, line 244
def build_and_send_request(method_name = :get, args = { }, options = { })
  _request = build_request(method_name, args, options)
  send_request(_request)
end
build_request(method_name = :get, args = { }, options = { }) click to toggle source

Builds the HTTP request

@param [Symbol] method_name (:get) @param [Hash] args @option args [Hash] :headers ({}) @option args [String] :path ('') @option args [Hash] :query ({}) @option args [Any] :body (nil) @param [Hash] options @option options [Hash] :default_request_headers (@default_request_headers) @option options [Hash] :headers @option options [Hash] :query

# File lib/vidispine/api/client/http_client.rb, line 203
def build_request(method_name = :get, args = { }, options = { })
  headers = args[:headers] || options[:headers] || { }
  path = args[:path] || ''
  query = args[:query] || options[:query] || { }
  body = args[:body]

  # Allow the default request headers to be overridden
  _default_request_headers = options.fetch(:default_request_headers, default_request_headers)
  _default_request_headers ||= { }
  _headers = _default_request_headers.merge(headers)

  @uri = build_uri(path, query, options)
  klass_name = request_method_name_to_class_name(method_name)
  klass = Net::HTTP.const_get(klass_name)

  _request = klass.new(@uri.request_uri, _headers)

  if _request.request_body_permitted?
    begin
      _body = (body and !body.is_a?(String)) ? JSON.generate(body) : body
      _request.body = _body if _body
    rescue => e
      logger.error { "Exception Processing Request Body: #{e.message}\n#{_body}"}
      raise
    end
  end

  _request
end
build_uri(path = '', query = nil, options = { }) click to toggle source

Compiles a full URI

@param [String] path @param [Hash|String|Nil] query @param [Hash] options @option options [Hash] :default_query_data @option options [Hash] :default_base_path

@return [URI]

# File lib/vidispine/api/client/http_client.rb, line 168
def build_uri(path = '', query = nil, options = { })
  _default_query_data = options.fetch(:default_query_data, default_query_data) || { }
  _default_base_path = options.fetch(:default_base_path, default_base_path)

  query = { } if query.nil?

  _query = query.is_a?(Hash) ? (default_query_data.merge(query)).map { |k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.respond_to?(:to_s) ? v.to_s : v)}" }.join('&') : query
  _path = "#{path}#{_query and _query.respond_to?(:empty?) and !_query.empty? ? "?#{_query}" : ''}"
  _path = File.join(_default_base_path, _path) if _default_base_path
  _path = File.join(base_uri, _path)
  URI.parse(_path)
end
delete(path, options = { }) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 249
def delete(path, options = { })
  build_and_send_request(:delete, { :path => path }, options)
end
format_body_for_log_output(obj) click to toggle source

Formats a HTTPRequest or HTTPResponse body for log output. @param [HTTPRequest|HTTPResponse] obj @return [String]

# File lib/vidispine/api/client/http_client.rb, line 110
def format_body_for_log_output(obj)
  if obj.content_type == 'application/json'
    if @log_pretty_print_body
      _body = obj.body
      output = JSON.pretty_generate(JSON.parse(_body)) rescue _body
      return output
    else
      return obj.body
    end
  elsif obj.content_type == 'application/xml'
    return obj.body
  else
    return obj.body.inspect
  end
end
get(path, options = { }) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 253
def get(path, options = { })
  build_and_send_request(:get, { :path => path }, options)
end
head(path, options = { }) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 257
def head(path, options = { })
  build_and_send_request(:head, { :path => path }, options)
end
initialize_http(args = { }) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 81
def initialize_http(args = { })
  @http_host_address = args[:http_host_address] ||= DEFAULT_HTTP_HOST_ADDRESS
  @http_host_port = args[:http_host_port] ||= DEFAULT_HTTP_HOST_PORT
  @http = Net::HTTP.new(http_host_address, http_host_port)
  use_ssl = args[:http_host_use_ssl]
  if use_ssl
    http_verify_mode = args.fetch(:http_verify_mode, OpenSSL::SSL::VERIFY_NONE)
    http.use_ssl = true
    http.verify_mode = http_verify_mode if http_verify_mode
  end

  http
end
initialize_logger(args = { }) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 71
def initialize_logger(args = { })
  @logger = args[:logger] ||= Logger.new(args[:log_to] || STDOUT)
  log_level = args[:log_level]
  if log_level
    @logger.level = log_level
    args[:logger] = @logger
  end
  @logger
end
options(path, options = { }) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 261
def options(path, options = { })
  build_and_send_request(:options, { :path => path }, options)
end
post(path, body, options = { }) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 269
def post(path, body, options = { })
  build_and_send_request(:post, { :path => path, :body => body }, options)
end
put(path, body, options = { }) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 265
def put(path, body, options = { })
  build_and_send_request(:put, { :path => path, :body => body }, options)
end
request_method_name_to_class_name(method_name) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 182
def request_method_name_to_class_name(method_name)
  method_name.to_s.capitalize
end
response_parsed() click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 143
def response_parsed
  @response_parsed ||= begin
    response_body = response.respond_to?(:body) ? response.body : ''

    case response.content_type
    when 'application/json'
       response_body.empty? ? response_body : JSON.parse(response_body) # rescue response
    else
       response_body
    end
  rescue => e
    logger.debug { "Error Parsing Response. #{e.message}\n#{response_body.inspect}" }
     raise
  end
end
send_request(request) click to toggle source

@param [HTTPRequest] request

# File lib/vidispine/api/client/http_client.rb, line 127
def send_request(request)
  @response_parsed = nil
  @request = request
  logger.debug { %(REQUEST: #{request.method} http#{http.use_ssl? ? 's' : ''}://#{http.address}:#{http.port}#{request.path} HEADERS: #{request.to_hash.inspect} #{log_request_body and request.request_body_permitted? ? "\n-- BODY BEGIN --\n#{format_body_for_log_output(request)}\n-- BODY END --" : ''}) }

  @request_time_start = Time.now
  @response = http.request(request)
  @request_time_end = Time.now
  logger.debug { %(RESPONSE: #{response.inspect} HEADERS: #{response.to_hash.inspect} #{log_response_body and response.respond_to?(:body) ? "\n-- BODY BEGIN --\n#{format_body_for_log_output(response)}\n-- BODY END--" : ''}\nTook: #{@request_time_end - @request_time_start} seconds) }
  #logger.debug { "Parse Response? #{@parse_response}" }

  raise HTTPAuthorizationError if @use_exceptions && @response.code == '401'

  @parse_response ? response_parsed : response.body
end
user_agent() click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 103
def user_agent
  default_request_headers['User-Agent']
end
user_agent=(value) click to toggle source
# File lib/vidispine/api/client/http_client.rb, line 95
def user_agent=(value)
  if (value)
    default_request_headers['User-Agent'] = value
  else
    default_request_headers.delete('User-Agent')
  end
end