Class: Stripe::StripeClient
- Inherits:
-
Object
- Object
- Stripe::StripeClient
- Defined in:
- lib/stripe/stripe_client.rb
Overview
StripeClient executes requests against the Stripe 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: FaradayStripeEncoder, RequestLogContext, StripeRequestMetrics, 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_key: nil, headers: {}, params: {}) ⇒ Object
-
#initialize(conn = nil) ⇒ StripeClient
constructor
Initializes a new StripeClient.
-
#request ⇒ Object
Executes the API call within the given block.
Constructor Details
#initialize(conn = nil) ⇒ StripeClient
Initializes a new StripeClient. Expects a Faraday connection object, and uses a default connection unless one is passed.
12 13 14 15 16 |
# File 'lib/stripe/stripe_client.rb', line 12 def initialize(conn = nil) self.conn = conn || self.class.default_conn @system_profiler = SystemProfiler.new @last_request_metrics = nil end |
Instance Attribute Details
#conn ⇒ Object
Returns the value of attribute conn.
8 9 10 |
# File 'lib/stripe/stripe_client.rb', line 8 def conn @conn end |
Class Method Details
.active_client ⇒ Object
18 19 20 |
# File 'lib/stripe/stripe_client.rb', line 18 def self.active_client Thread.current[:stripe_client] || default_client end |
.default_client ⇒ Object
22 23 24 25 |
# File 'lib/stripe/stripe_client.rb', line 22 def self.default_client Thread.current[:stripe_client_default_client] ||= StripeClient.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 StripeClient object should be preferred.
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/stripe/stripe_client.rb', line 30 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[:stripe_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 = Stripe.proxy if Stripe.proxy if Stripe.verify_ssl_certs conn.ssl.verify = true conn.ssl.cert_store = Stripe.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 `Stripe.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 86 87 88 89 90 |
# File 'lib/stripe/stripe_client.rb', line 73 def self.should_retry?(error, num_retries) return false if num_retries >= Stripe.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) if error.is_a?(Faraday::ClientError) && error.response # 409 conflict return true if error.response[:status] == 409 end false end |
.sleep_time(num_retries) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/stripe/stripe_client.rb', line 92 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 = [ Stripe.initial_network_retry_delay * (2**(num_retries - 1)), Stripe.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 = [Stripe.initial_network_retry_delay, sleep_seconds].max sleep_seconds end |
Instance Method Details
#execute_request(method, path, api_base: nil, api_key: nil, headers: {}, params: {}) ⇒ Object
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 194 195 196 197 198 199 200 201 202 |
# File 'lib/stripe/stripe_client.rb', line 129 def execute_request(method, path, api_base: nil, api_key: nil, headers: {}, params: {}) api_base ||= Stripe.api_base api_key ||= Stripe.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 = FaradayStripeEncoder.new url = api_url(path, api_base) # 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["Stripe-Account"] context.api_key = api_key context.api_version = headers["Stripe-Version"] context.body = body ? params_encoder.encode(body) : nil context.idempotency_key = headers["Idempotency-Key"] context.method = method context.path = path context.query_params = if query_params params_encoder.encode(query_params) end # note that both request body and query params will be passed through # `FaradayStripeEncoder` http_resp = execute_request_with_rescues(api_base, context) do conn.run_request(method, url, body, headers) do |req| req..open_timeout = Stripe.open_timeout req..params_encoder = params_encoder req..timeout = Stripe.read_timeout req.params = query_params unless query_params.nil? end end begin resp = StripeResponse.from_faraday_response(http_resp) rescue JSON::ParserError raise general_api_error(http_resp.status, http_resp.body) end # Allows StripeClient#request to return a response object to a caller. @last_response = resp [resp, api_key] end |
#request ⇒ Object
Executes the API call within the given block. Usage looks like:
client = StripeClient.new
charge, resp = client.request { Charge.create }
116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/stripe/stripe_client.rb', line 116 def request @last_response = nil old_stripe_client = Thread.current[:stripe_client] Thread.current[:stripe_client] = self begin res = yield [res, @last_response] ensure Thread.current[:stripe_client] = old_stripe_client end end |