Class: Supercast::Client
- Inherits:
-
Object
- Object
- Supercast::Client
- Defined in:
- lib/supercast/client.rb
Overview
Client executes requests against the Supercast API and allows a user to recover both a resource a call returns as well as a response object that contains information on the HTTP call.
Defined Under Namespace
Classes: FaradaySupercastEncoder, RequestLogContext, SystemProfiler
Instance Attribute Summary collapse
-
#conn ⇒ Object
Returns the value of attribute conn.
Class Method Summary collapse
- .active_client ⇒ Object
- .default_client ⇒ Object
-
.default_conn ⇒ Object
A default Faraday connection to be used when one isn’t configured.
-
.should_retry?(error, num_retries) ⇒ Boolean
Checks if an error is a problem that we should retry on.
- .sleep_time(num_retries) ⇒ Object
Instance Method Summary collapse
-
#execute_request(method, path, api_base: nil, api_version: nil, api_key: nil, headers: {}, params: {}) ⇒ Object
rubocop:disable Metrics/AbcSize Metrics/MethodLength.
-
#initialize(conn = nil) ⇒ Client
constructor
Initializes a new Client.
-
#request ⇒ Object
Executes the API call within the given block.
Constructor Details
#initialize(conn = nil) ⇒ Client
Initializes a new Client. Expects a Faraday connection object, and uses a default connection unless one is passed.
12 13 14 15 |
# File 'lib/supercast/client.rb', line 12 def initialize(conn = nil) self.conn = conn || self.class.default_conn @system_profiler = SystemProfiler.new end |
Instance Attribute Details
#conn ⇒ Object
Returns the value of attribute conn.
8 9 10 |
# File 'lib/supercast/client.rb', line 8 def conn @conn end |
Class Method Details
.active_client ⇒ Object
17 18 19 |
# File 'lib/supercast/client.rb', line 17 def self.active_client Thread.current[:supercast_client] || default_client end |
.default_client ⇒ Object
21 22 23 24 |
# File 'lib/supercast/client.rb', line 21 def self.default_client Thread.current[:supercast_client_default_client] ||= Client.new(default_conn) end |
.default_conn ⇒ Object
A default Faraday connection to be used when one isn’t configured. This object should never be mutated, and instead instantiating your own connection and wrapping it in a Client object should be preferred.
29 30 31 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/supercast/client.rb', line 29 def self.default_conn # We're going to keep connections around so that we can take advantage # of connection re-use, so make sure that we have a separate connection # object per thread. Thread.current[:supercast_client_default_conn] ||= begin conn = Faraday.new do |builder| builder.use Faraday::Request::Multipart builder.use Faraday::Request::UrlEncoded builder.use Faraday::Response::RaiseError # Net::HTTP::Persistent doesn't seem to do well on Windows or JRuby, # so fall back to default there. if Gem.win_platform? || RUBY_PLATFORM == 'java' builder.adapter :net_http else builder.adapter :net_http_persistent end end conn.proxy = Supercast.proxy if Supercast.proxy if Supercast.verify_ssl_certs conn.ssl.verify = true conn.ssl.cert_store = Supercast.ca_store else conn.ssl.verify = false unless @verify_ssl_warned @verify_ssl_warned = true warn('WARNING: Running without SSL cert verification. ' \ 'You should never do this in production. ' \ 'Execute `Supercast.verify_ssl_certs = true` to enable ' \ 'verification.') end end conn end end |
.should_retry?(error, num_retries) ⇒ Boolean
Checks if an error is a problem that we should retry on. This includes both socket errors that may represent an intermittent problem and some special HTTP statuses.
73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/supercast/client.rb', line 73 def self.should_retry?(error, num_retries) return false if num_retries >= Supercast.max_network_retries # Retry on timeout-related problems (either on open or read). return true if error.is_a?(Faraday::TimeoutError) # Destination refused the connection, the connection was reset, or a # variety of other connection failures. This could occur from a single # saturated server, so retry in case it's intermittent. return true if error.is_a?(Faraday::ConnectionFailed) false end |
.sleep_time(num_retries) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/supercast/client.rb', line 87 def self.sleep_time(num_retries) # Apply exponential backoff with initial_network_retry_delay on the # number of num_retries so far as inputs. Do not allow the number to # exceed max_network_retry_delay. sleep_seconds = [ Supercast.initial_network_retry_delay * (2**(num_retries - 1)), Supercast.max_network_retry_delay ].min # Apply some jitter by randomizing the value in the range of # (sleep_seconds / 2) to (sleep_seconds). sleep_seconds *= (0.5 * (1 + rand)) # But never sleep less than the base sleep seconds. sleep_seconds = [Supercast.initial_network_retry_delay, sleep_seconds].max sleep_seconds end |
Instance Method Details
#execute_request(method, path, api_base: nil, api_version: nil, api_key: nil, headers: {}, params: {}) ⇒ Object
rubocop:disable Metrics/AbcSize Metrics/MethodLength
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 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 |
# File 'lib/supercast/client.rb', line 124 def execute_request(method, path, api_base: nil, api_version: nil, api_key: nil, headers: {}, params: {}) # rubocop:disable Metrics/AbcSize Metrics/MethodLength api_base ||= Supercast.api_base api_version ||= Supercast.api_version api_key ||= Supercast.api_key params = Util.objects_to_ids(params) check_api_key!(api_key) body = nil query_params = nil case method.to_s.downcase.to_sym when :get, :head, :delete query_params = params else body = params end # This works around an edge case where we end up with both query # parameters in `query_params` and query parameters that are appended # onto the end of the given path. In this case, Faraday will silently # discard the URL's parameters which may break a request. # # Here we decode any parameters that were added onto the end of a path # and add them to `query_params` so that all parameters end up in one # place and all of them are correctly included in the final request. u = URI.parse(path) unless u.query.nil? query_params ||= {} query_params = Hash[URI.decode_www_form(u.query)].merge(query_params) # Reset the path minus any query parameters that were specified. path = u.path end headers = request_headers(api_key, method).update(Util.normalize_headers(headers)) params_encoder = FaradaySupercastEncoder.new url = api_url(path, api_base, api_version) # stores information on the request we're about to make so that we don't # have to pass as many parameters around for logging. context = RequestLogContext.new context.account = headers['Supercast-Account'] context.api_key = api_key context.api_version = headers['Supercast-Version'] context.body = body ? params_encoder.encode(body) : nil context.method = method context.path = path context.query_params = (params_encoder.encode(query_params) if query_params) # note that both request body and query params will be passed through # `FaradaySupercastEncoder` http_resp = execute_request_with_rescues(api_base, context) do conn.run_request(method, url, body, headers) do |req| req..open_timeout = Supercast.open_timeout req..params_encoder = params_encoder req..timeout = Supercast.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 # Allows Client#request to return a response object to a caller. @last_response = resp [resp, api_key] end |
#request ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/supercast/client.rb', line 111 def request @last_response = nil old_supercast_client = Thread.current[:supercast_client] Thread.current[:supercast_client] = self begin res = yield [res, @last_response] ensure Thread.current[:supercast_client] = old_supercast_client end end |