Class: Files::ApiClient

Inherits:
Object
  • Object
show all
Defined in:
lib/files.com/api_client.rb

Defined Under Namespace

Classes: RequestLogContext

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(conn = nil) ⇒ ApiClient

Returns a new instance of ApiClient.



7
8
9
10
11
# File 'lib/files.com/api_client.rb', line 7

def initialize(conn = nil)
  self.conn = conn || self.class.default_conn
  @system_profiler = SystemProfiler.new
  @last_request_metrics = nil
end

Instance Attribute Details

#connObject

Returns the value of attribute conn.



5
6
7
# File 'lib/files.com/api_client.rb', line 5

def conn
  @conn
end

Class Method Details

.active_clientObject



13
14
15
# File 'lib/files.com/api_client.rb', line 13

def self.active_client
  Thread.current[:files_api_client] || default_client
end

.default_clientObject



17
18
19
# File 'lib/files.com/api_client.rb', line 17

def self.default_client
  Thread.current[:files_api_client_default_client] ||= ApiClient.new(default_conn)
end

.default_connObject



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/files.com/api_client.rb', line 21

def self.default_conn
  Thread.current[:files_api_client_default_conn] ||= begin
    conn = Faraday.new do |builder|
      builder.use Faraday::Request::Multipart
      builder.use Faraday::Request::UrlEncoded
      builder.use Faraday::Response::RaiseError

      if Gem.win_platform? || RUBY_PLATFORM == "java"
        builder.adapter :net_http
      else
        builder.adapter :net_http_persistent
      end
    end

    conn.proxy = Files.proxy if Files.proxy
    conn.ssl.verify = true

    conn
  end
end

.should_retry?(error, num_retries) ⇒ Boolean

Returns:

  • (Boolean)


42
43
44
45
46
47
48
# File 'lib/files.com/api_client.rb', line 42

def self.should_retry?(error, num_retries)
  return false if num_retries >= Files.max_network_retries
  return true if error.is_a?(Faraday::TimeoutError)
  return true if error.is_a?(Faraday::ConnectionFailed)

  false
end

.sleep_time(num_retries) ⇒ Object



50
51
52
53
54
55
56
57
# File 'lib/files.com/api_client.rb', line 50

def self.sleep_time(num_retries)
  sleep_seconds = [
    Files.initial_network_retry_delay * (2**(num_retries - 1)),
    Files.max_network_retry_delay
  ].min
  sleep_seconds *= (0.5 * (1 + rand))
  [ Files.initial_network_retry_delay, sleep_seconds ].max
end

Instance Method Details

#execute_request(method, path, base_url: nil, api_key: nil, session_id: nil, headers: {}, params: {}) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/files.com/api_client.rb', line 72

def execute_request(method, path, base_url: nil, api_key: nil, session_id: nil, headers: {}, params: {})
  base_url ||= Files.base_url
  session_id ||= Files.session_id

  if session_id and session_id != ""
    check_session_id!(session_id)
  elsif path !~ /^\/sessions/ # TODO: automate this to refer to any unauthenticated endpoint
    api_key ||= Files.api_key
    check_api_key!(api_key)
  end

  body = nil
  query_params = nil
  case method.to_s.downcase.to_sym
  when :get, :head, :delete
    query_params = params
  else
    body = params
  end

  headers = request_headers(api_key, session_id, method).update(headers)
  url = api_url(path, base_url)

  context = RequestLogContext.new
  context.api_key      = api_key
  context.body         = body
  context.method       = method
  context.path         = path
  context.query_params = query_params if query_params
  context.session_id   = session_id

  http_resp = execute_request_with_rescues(base_url, context) do
    conn.run_request(method, url, body, headers) do |req|
      req.options.open_timeout = Files.open_timeout
      req.options.timeout = Files.read_timeout
      req.params = query_params unless query_params.nil?
    end
  end

  begin
    resp = Response.from_faraday_response(http_resp)
  rescue JSON::ParserError
    raise general_api_error(http_resp.status, http_resp.body)
  end

  @last_response = resp
  [ resp, api_key, session_id ]
end

#execute_request_with_rescues(base_url, context, skip_body_logging = false) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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/files.com/api_client.rb', line 157

def execute_request_with_rescues(base_url, context, skip_body_logging = false)
  num_retries = 0
  begin
    request_start = Time.now
    log_request(context, num_retries, skip_body_logging)
    resp = yield
    log_response(context, request_start, resp.status, resp.body, skip_body_logging)
  rescue StandardError => e
    error_context = context

    if e.respond_to?(:response) && e.response
      error_context = context
      log_response(error_context, request_start,
                   e.response[:status], e.response[:body], skip_body_logging
      )
    else
      log_response_error(error_context, request_start, e)
    end

    if self.class.should_retry?(e, num_retries)
      num_retries += 1
      sleep self.class.sleep_time(num_retries)
      retry
    end

    case e
    when Faraday::ClientError
      if e.response
        handle_error_response(e.response, error_context)
      else
        handle_network_error(e, error_context, num_retries, base_url)
      end

    else
      raise
    end
  end

  resp
end

#remote_request(method, url, headers = {}, body = nil) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/files.com/api_client.rb', line 121

def remote_request(method, url, headers = {}, body = nil)
  context = RequestLogContext.new
  context.method       = method
  context.path         = url

  execute_request_with_rescues(Files.base_url, context, true) do
    conn.run_request(method, url, body, headers) do |req|
      req.options.open_timeout = Files.open_timeout
      req.options.timeout = Files.read_timeout
      yield(req) if block_given?
    end
  end
end

#requestObject



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/files.com/api_client.rb', line 59

def request
  @last_response = nil
  old_files_api_client = Thread.current[:files_api_client]
  Thread.current[:files_api_client] = self

  begin
    res = yield
    [ res, @last_response ]
  ensure
    Thread.current[:files_api_client] = old_files_api_client
  end
end