Class: Ubiquity::Iconik::API::Client::HTTPClient

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

Defined Under Namespace

Classes: HTTPAuthorizationError

Constant Summary collapse

DEFAULT_HTTP_HOST_ADDRESS =
'app.iconik.io'
DEFAULT_HTTP_HOST_PORT =
443
DEFAULT_BASE_PATH =
'/API/'
DEFAULT_APP_ID =
''
DEFAULT_HEADER_CONTENT_TYPE =
'application/json; charset=utf-8'
DEFAULT_HEADER_ACCEPTS =
'application/json'
DEFAULT_HEADER_AUTH_KEY =
'Auth-Token'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = { }) ⇒ HTTPClient

Returns a new instance of HTTPClient.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 46

def initialize(args = { })
  args = args.dup

  @use_exceptions = args.fetch(:use_exceptions, true)
  @max_retry_count = 1
  @retry_count = 0

  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[:default_base_path] || DEFAULT_BASE_PATH

  # @user_agent_default = "Ubiquity::Iconik Ruby SDK Version #{Ubiquity::Iconik::VERSION}"

  @app_id = args[:application_id] || args[:app_id] || DEFAULT_APP_ID

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

  @header_auth_key = args[:header_auth_key] || DEFAULT_HEADER_AUTH_KEY

  @default_request_headers = {
    # 'User-Agent' => @user_agent_default,
    'Content-Type' => content_type,
    'Accept' => accepts,
    'App-ID' => @app_id,
  }

  self.token = args[:token] || ''

  @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

#app_idObject

Returns the value of attribute app_id.



32
33
34
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 32

def app_id
  @app_id
end

#base_uriObject

Returns the value of attribute base_uri.



21
22
23
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 21

def base_uri
  @base_uri
end

#default_request_headersObject

Returns the value of attribute default_request_headers.



24
25
26
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 24

def default_request_headers
  @default_request_headers
end

#header_auth_keyObject

Returns the value of attribute header_auth_key.



24
25
26
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 24

def header_auth_key
  @header_auth_key
end

#httpObject

Returns the value of attribute http.



21
22
23
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 21

def http
  @http
end

#http_host_addressObject

Returns the value of attribute http_host_address.



21
22
23
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 21

def http_host_address
  @http_host_address
end

#http_host_portObject

Returns the value of attribute http_host_port.



21
22
23
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 21

def http_host_port
  @http_host_port
end

#log_pretty_print_bodyObject

Returns the value of attribute log_pretty_print_body.



27
28
29
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 27

def log_pretty_print_body
  @log_pretty_print_body
end

#log_request_bodyObject

Returns the value of attribute log_request_body.



27
28
29
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 27

def log_request_body
  @log_request_body
end

#log_response_bodyObject

Returns the value of attribute log_response_body.



27
28
29
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 27

def log_response_body
  @log_response_body
end

#loggerObject

Returns the value of attribute logger.



21
22
23
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 21

def logger
  @logger
end

#passwordObject

Returns the value of attribute password.



22
23
24
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 22

def password
  @password
end

#requestObject

Returns the value of attribute request.



29
30
31
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 29

def request
  @request
end

#responseObject

Returns the value of attribute response.



29
30
31
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 29

def response
  @response
end

#tokenObject

Returns the value of attribute token.



32
33
34
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 32

def token
  @token
end

#token_dataObject

Returns the value of attribute token_data.



32
33
34
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 32

def token_data
  @token_data
end

#use_exceptionsObject

Returns the value of attribute use_exceptions.



29
30
31
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 29

def use_exceptions
  @use_exceptions
end

#usernameObject

Returns the value of attribute username.



22
23
24
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 22

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)


172
173
174
175
176
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 172

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


196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 196

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

#default_header_auth_setObject



306
307
308
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 306

def default_header_auth_set
  @default_request_headers[header_auth_key] = @token.respond_to?(:to_s) ? @token.to_s : @token
end

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



222
223
224
225
226
227
228
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 222

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)


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

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



230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 230

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



243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 243

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



96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 96

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.fetch(:http_host_use_ssl, true)
  if use_ssl
    @http.use_ssl = true
    http_verify_mode = args[:http_host_ssl_verify_mode] #|| OpenSSL::SSL::VERIFY_NONE
    @http.verify_mode = http_verify_mode if http_verify_mode
  end

  http
end

#initialize_logger(args = { }) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 86

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



257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 257

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



287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 287

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



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 270

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



179
180
181
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 179

def request_method_name_to_class_name(method_name)
  method_name.to_s.capitalize
end

#response_parsedObject



155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 155

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)


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 131

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 --" : ''}) }

  @response = http.request(request)
  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--" : ''}) }
  #logger.debug { "Parse Response? #{@parse_response}" }

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

  @retry_count = 0
  @original_exception = nil

  @parse_response ? response_parsed : response.body

rescue => e
  raise if @retry_count >= @max_retry_count

  @retry_count += 1
  logger.warn { "Retrying request. Attempt #{@retry_count} '#{e.message}'" }
  retry
end

#token?Boolean

Determines if token is set

Returns:

  • (Boolean)


311
312
313
# File 'lib/ubiquity/iconik/api/client/http_client.rb', line 311

def token?
  (@token.respond_to?(:empty?) && !@token.empty?)
end