Class: Vidispine::API::Client::HTTPClient

Inherits:
Object
  • Object
show all
Defined in:
lib/vidispine/api/client/http_client.rb

Defined Under Namespace

Classes: HTTPAuthorizationError

Constant Summary collapse

DEFAULT_HTTP_HOST_ADDRESS =
'localhost'
DEFAULT_HTTP_HOST_PORT =
8080
DEFAULT_USERNAME =
'admin'
DEFAULT_PASSWORD =
'password'
DEFAULT_BASE_PATH =
'API/'
DEFAULT_HEADER_CONTENT_TYPE =
'application/json; charset=utf-8'
DEFAULT_HEADER_ACCEPTS =
'application/json'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = { }) ⇒ HTTPClient

Returns a new instance of HTTPClient.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/vidispine/api/client/http_client.rb', line 32

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}" }

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

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

  # @user_agent_default = "#{@hostname}:#{@username} Ruby SDK Version #{Vidispine::VERSION}"

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

  content_type = args[:content_type_header] ||= DEFAULT_HEADER_CONTENT_TYPE
  accepts = args[:accepts_header] ||= args[:accept_header] || DEFAULT_HEADER_ACCEPTS

  @default_request_headers = {
    'Content-Type' => content_type,
    'Accept' => accepts,
    authorization_header_key => authorization_header_value,
  }

  @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

Instance Attribute Details

#authorization_header_keyObject

Returns the value of attribute authorization_header_key.



15
16
17
# File 'lib/vidispine/api/client/http_client.rb', line 15

def authorization_header_key
  @authorization_header_key
end

#authorization_header_valueObject

Returns the value of attribute authorization_header_value.



15
16
17
# File 'lib/vidispine/api/client/http_client.rb', line 15

def authorization_header_value
  @authorization_header_value
end

#base_uriObject

Returns the value of attribute base_uri.



12
13
14
# File 'lib/vidispine/api/client/http_client.rb', line 12

def base_uri
  @base_uri
end

#default_base_pathObject

Returns the value of attribute default_base_path.



12
13
14
# File 'lib/vidispine/api/client/http_client.rb', line 12

def default_base_path
  @default_base_path
end

#default_request_headersObject

Returns the value of attribute default_request_headers.



15
16
17
# File 'lib/vidispine/api/client/http_client.rb', line 15

def default_request_headers
  @default_request_headers
end

#httpObject

Returns the value of attribute http.



12
13
14
# File 'lib/vidispine/api/client/http_client.rb', line 12

def http
  @http
end

#http_host_addressObject

Returns the value of attribute http_host_address.



12
13
14
# File 'lib/vidispine/api/client/http_client.rb', line 12

def http_host_address
  @http_host_address
end

#http_host_portObject

Returns the value of attribute http_host_port.



12
13
14
# File 'lib/vidispine/api/client/http_client.rb', line 12

def http_host_port
  @http_host_port
end

#log_pretty_print_bodyObject

Returns the value of attribute log_pretty_print_body.



18
19
20
# File 'lib/vidispine/api/client/http_client.rb', line 18

def log_pretty_print_body
  @log_pretty_print_body
end

#log_request_bodyObject

Returns the value of attribute log_request_body.



18
19
20
# File 'lib/vidispine/api/client/http_client.rb', line 18

def log_request_body
  @log_request_body
end

#log_response_bodyObject

Returns the value of attribute log_response_body.



18
19
20
# File 'lib/vidispine/api/client/http_client.rb', line 18

def log_response_body
  @log_response_body
end

#loggerObject

Returns the value of attribute logger.



12
13
14
# File 'lib/vidispine/api/client/http_client.rb', line 12

def logger
  @logger
end

#passwordObject

Returns the value of attribute password.



13
14
15
# File 'lib/vidispine/api/client/http_client.rb', line 13

def password
  @password
end

#requestObject

Returns the value of attribute request.



20
21
22
# File 'lib/vidispine/api/client/http_client.rb', line 20

def request
  @request
end

#responseObject

Returns the value of attribute response.



20
21
22
# File 'lib/vidispine/api/client/http_client.rb', line 20

def response
  @response
end

#use_exceptionsObject

Returns the value of attribute use_exceptions.



20
21
22
# File 'lib/vidispine/api/client/http_client.rb', line 20

def use_exceptions
  @use_exceptions
end

#usernameObject

Returns the value of attribute username.



13
14
15
# File 'lib/vidispine/api/client/http_client.rb', line 13

def username
  @username
end

Instance Method Details

#build_uri(path = '', query = nil) ⇒ URI

Parameters:

  • path (String) (defaults to: '')
  • query (Hash|String|Nil) (defaults to: nil)

Returns:

  • (URI)


148
149
150
151
152
# File 'lib/vidispine/api/client/http_client.rb', line 148

def build_uri(path = '', query = nil)
  _query = query.is_a?(Hash) ? 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}" : ''}"
  URI.parse(File.join(base_uri, _path))
end

#call_method(method_name = :get, args = { }, options = { }) ⇒ Object

Parameters:

  • method_name (Symbol) (defaults to: :get)

    (:get)

  • args (Hash) (defaults to: { })
  • options (Hash) (defaults to: { })

Options Hash (args):

  • :headers (Hash) — default: {}
  • :path (String) — default: ''
  • :query (Hash) — default: {}
  • :body (Any) — default: nil

Options Hash (options):

  • :default_request_headers (Hash) — default: @default_request_headers


172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/vidispine/api/client/http_client.rb', line 172

def call_method(method_name = :get, args = { }, options = { })
  headers = args[:headers] || options[:headers] || { }
  path = args[:path] || ''
  query = args[: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)
  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?
    _body = (body and !body.is_a?(String)) ? JSON.generate(body) : body
    logger.debug { "Processing Body: '#{_body}'" }
    request.body = _body if _body
  end

  send_request(request)
end

#delete(path, options = { }) ⇒ Object



198
199
200
201
202
203
204
# File 'lib/vidispine/api/client/http_client.rb', line 198

def delete(path, options = { })
  query = options.fetch(:query, { })
  base_path = options[:base_path] || ( path.start_with?(@default_base_path) ? '' : @default_base_path )
  @uri = build_uri(File.join(base_path, path), query)
  request = Net::HTTP::Delete.new(@uri.request_uri, default_request_headers)
  send_request(request)
end

#format_body_for_log_output(obj) ⇒ String

Formats a HTTPRequest or HTTPResponse body for log output.

Parameters:

  • obj (HTTPRequest|HTTPResponse)

Returns:

  • (String)


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/vidispine/api/client/http_client.rb', line 98

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 = { }) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/vidispine/api/client/http_client.rb', line 206

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

  query ||= options.fetch(:query, { })
  base_path = options[:base_path] || ( path.start_with?(@default_base_path) ? '' : @default_base_path )
  @uri = build_uri(File.join(base_path, path), query)
  request = Net::HTTP::Get.new(@uri.request_uri, _headers)
  send_request(request)
end

#head(path, options = { }) ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/vidispine/api/client/http_client.rb', line 219

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

  query ||= options.fetch(:query, { })
  base_path = options[:base_path] || ( path.start_with?(@default_base_path) ? '' : @default_base_path )
  @uri = build_uri(File.join(base_path, path), query)

  request = Net::HTTP::Head.new(@uri.request_uri, _headers)
  send_request(request)
end

#initialize_http(args = { }) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/vidispine/api/client/http_client.rb', line 80

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
    # @TODO Add SSL Support
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  end

  http
end

#initialize_logger(args = { }) ⇒ Object



70
71
72
73
74
75
76
77
78
# File 'lib/vidispine/api/client/http_client.rb', line 70

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 = { }) ⇒ Object



233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/vidispine/api/client/http_client.rb', line 233

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

  query ||= options.fetch(:query, { })
  base_path = options[:base_path] || ( path.start_with?(@default_base_path) ? '' : @default_base_path )
  @uri = build_uri(File.join(base_path, path), query)
  request = Net::HTTP::Options.new(@uri.request_uri, _headers)
  send_request(request)
end

#post(path, body, options = { }) ⇒ Object



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/vidispine/api/client/http_client.rb', line 263

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

  query = options.fetch(:query, { })
  base_path = options[:base_path] || ( path.start_with?(@default_base_path) ? '' : @default_base_path )
  @uri = build_uri(File.join(base_path, path), query)

  request = Net::HTTP::Post.new(@uri.request_uri, _headers)

  body = JSON.generate(body) if body and !body.is_a?(String)

  request.body = body if body
  send_request(request)
end

#put(path, body, options = { }) ⇒ Object



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/vidispine/api/client/http_client.rb', line 246

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

  query = options.fetch(:query, { })
  base_path = options[:base_path] || ( path.start_with?(@default_base_path) ? '' : @default_base_path )
  @uri = build_uri(File.join(base_path, path), query)
  request = Net::HTTP::Put.new(@uri.request_uri, _headers)

  body = JSON.generate(body) if body and !body.is_a?(String)

  request.body = body if body
  send_request(request)
end

#request_method_name_to_class_name(method_name) ⇒ Object



155
156
157
# File 'lib/vidispine/api/client/http_client.rb', line 155

def request_method_name_to_class_name(method_name)
  method_name.to_s.capitalize
end

#response_parsedObject



131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/vidispine/api/client/http_client.rb', line 131

def response_parsed
  @response_parsed ||= begin
    response_body = response.respond_to?(:body) ? response.body : ''
    logger.debug { "Parsing Response. #{response_body.inspect}" }

    case response.content_type
    when 'application/json'
       response_body.empty? ? response_body : JSON.parse(response_body) # rescue response
     else
       response_body
    end
  end
end

#send_request(request) ⇒ Object

Parameters:

  • request (HTTPRequest)

Raises:



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/vidispine/api/client/http_client.rb', line 115

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