stripe 4.24.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +17 -4
  3. data/.rubocop_todo.yml +10 -9
  4. data/.travis.yml +1 -5
  5. data/CHANGELOG.md +22 -0
  6. data/Gemfile +2 -12
  7. data/README.md +10 -10
  8. data/Rakefile +8 -7
  9. data/VERSION +1 -1
  10. data/lib/stripe.rb +56 -15
  11. data/lib/stripe/api_operations/list.rb +0 -6
  12. data/lib/stripe/connection_manager.rb +131 -0
  13. data/lib/stripe/error_object.rb +94 -0
  14. data/lib/stripe/errors.rb +15 -2
  15. data/lib/stripe/list_object.rb +2 -1
  16. data/lib/stripe/multipart_encoder.rb +131 -0
  17. data/lib/stripe/object_types.rb +0 -1
  18. data/lib/stripe/resources.rb +0 -1
  19. data/lib/stripe/resources/account.rb +1 -5
  20. data/lib/stripe/resources/account_link.rb +1 -1
  21. data/lib/stripe/resources/alipay_account.rb +1 -1
  22. data/lib/stripe/resources/apple_pay_domain.rb +1 -1
  23. data/lib/stripe/resources/application_fee.rb +1 -12
  24. data/lib/stripe/resources/application_fee_refund.rb +1 -1
  25. data/lib/stripe/resources/balance.rb +1 -1
  26. data/lib/stripe/resources/balance_transaction.rb +1 -1
  27. data/lib/stripe/resources/bank_account.rb +1 -1
  28. data/lib/stripe/resources/bitcoin_receiver.rb +1 -1
  29. data/lib/stripe/resources/bitcoin_transaction.rb +1 -1
  30. data/lib/stripe/resources/capability.rb +1 -1
  31. data/lib/stripe/resources/card.rb +1 -1
  32. data/lib/stripe/resources/charge.rb +7 -69
  33. data/lib/stripe/resources/checkout/session.rb +1 -1
  34. data/lib/stripe/resources/country_spec.rb +1 -1
  35. data/lib/stripe/resources/coupon.rb +1 -1
  36. data/lib/stripe/resources/credit_note.rb +1 -1
  37. data/lib/stripe/resources/customer.rb +3 -63
  38. data/lib/stripe/resources/customer_balance_transaction.rb +1 -1
  39. data/lib/stripe/resources/discount.rb +1 -1
  40. data/lib/stripe/resources/dispute.rb +1 -7
  41. data/lib/stripe/resources/ephemeral_key.rb +1 -1
  42. data/lib/stripe/resources/event.rb +1 -1
  43. data/lib/stripe/resources/exchange_rate.rb +1 -1
  44. data/lib/stripe/resources/file.rb +3 -13
  45. data/lib/stripe/resources/file_link.rb +1 -1
  46. data/lib/stripe/resources/invoice.rb +6 -1
  47. data/lib/stripe/resources/invoice_item.rb +1 -1
  48. data/lib/stripe/resources/invoice_line_item.rb +1 -1
  49. data/lib/stripe/resources/issuing/authorization.rb +1 -1
  50. data/lib/stripe/resources/issuing/card.rb +1 -1
  51. data/lib/stripe/resources/issuing/card_details.rb +1 -1
  52. data/lib/stripe/resources/issuing/cardholder.rb +1 -1
  53. data/lib/stripe/resources/issuing/dispute.rb +1 -1
  54. data/lib/stripe/resources/issuing/transaction.rb +1 -1
  55. data/lib/stripe/resources/login_link.rb +1 -1
  56. data/lib/stripe/resources/order.rb +1 -9
  57. data/lib/stripe/resources/order_return.rb +1 -1
  58. data/lib/stripe/resources/payment_intent.rb +1 -1
  59. data/lib/stripe/resources/payment_method.rb +1 -1
  60. data/lib/stripe/resources/payout.rb +1 -7
  61. data/lib/stripe/resources/person.rb +1 -1
  62. data/lib/stripe/resources/plan.rb +1 -1
  63. data/lib/stripe/resources/product.rb +1 -1
  64. data/lib/stripe/resources/radar/early_fraud_warning.rb +1 -1
  65. data/lib/stripe/resources/radar/value_list.rb +1 -1
  66. data/lib/stripe/resources/radar/value_list_item.rb +1 -1
  67. data/lib/stripe/resources/recipient.rb +1 -5
  68. data/lib/stripe/resources/recipient_transfer.rb +1 -1
  69. data/lib/stripe/resources/refund.rb +1 -1
  70. data/lib/stripe/resources/reporting/report_run.rb +1 -1
  71. data/lib/stripe/resources/reporting/report_type.rb +1 -1
  72. data/lib/stripe/resources/reversal.rb +1 -1
  73. data/lib/stripe/resources/review.rb +1 -1
  74. data/lib/stripe/resources/setup_intent.rb +1 -1
  75. data/lib/stripe/resources/sigma/scheduled_query_run.rb +1 -1
  76. data/lib/stripe/resources/sku.rb +1 -1
  77. data/lib/stripe/resources/source.rb +1 -7
  78. data/lib/stripe/resources/source_transaction.rb +1 -1
  79. data/lib/stripe/resources/subscription.rb +9 -9
  80. data/lib/stripe/resources/subscription_item.rb +1 -1
  81. data/lib/stripe/resources/subscription_schedule.rb +1 -1
  82. data/lib/stripe/resources/tax_id.rb +1 -1
  83. data/lib/stripe/resources/tax_rate.rb +1 -1
  84. data/lib/stripe/resources/terminal/connection_token.rb +1 -1
  85. data/lib/stripe/resources/terminal/location.rb +1 -1
  86. data/lib/stripe/resources/terminal/reader.rb +1 -1
  87. data/lib/stripe/resources/three_d_secure.rb +1 -1
  88. data/lib/stripe/resources/token.rb +1 -1
  89. data/lib/stripe/resources/topup.rb +1 -1
  90. data/lib/stripe/resources/transfer.rb +1 -6
  91. data/lib/stripe/resources/usage_record.rb +1 -17
  92. data/lib/stripe/resources/usage_record_summary.rb +1 -1
  93. data/lib/stripe/resources/webhook_endpoint.rb +1 -1
  94. data/lib/stripe/stripe_client.rb +281 -183
  95. data/lib/stripe/stripe_object.rb +4 -23
  96. data/lib/stripe/stripe_response.rb +53 -21
  97. data/lib/stripe/util.rb +10 -11
  98. data/lib/stripe/version.rb +1 -1
  99. data/lib/stripe/webhook.rb +1 -1
  100. data/stripe.gemspec +6 -9
  101. data/test/stripe/account_test.rb +0 -16
  102. data/test/stripe/api_operations_test.rb +2 -2
  103. data/test/stripe/api_resource_test.rb +2 -10
  104. data/test/stripe/charge_test.rb +0 -16
  105. data/test/stripe/connection_manager_test.rb +138 -0
  106. data/test/stripe/customer_test.rb +1 -44
  107. data/test/stripe/errors_test.rb +29 -8
  108. data/test/stripe/file_test.rb +0 -10
  109. data/test/stripe/invoice_test.rb +17 -1
  110. data/test/stripe/list_object_test.rb +0 -16
  111. data/test/stripe/login_link_test.rb +1 -1
  112. data/test/stripe/multipart_encoder_test.rb +130 -0
  113. data/test/stripe/payment_intent_test.rb +1 -1
  114. data/test/stripe/setup_intent_test.rb +1 -1
  115. data/test/stripe/source_test.rb +0 -18
  116. data/test/stripe/stripe_client_test.rb +214 -29
  117. data/test/stripe/stripe_object_test.rb +7 -35
  118. data/test/stripe/stripe_response_test.rb +70 -24
  119. data/test/stripe/subscription_test.rb +2 -2
  120. data/test/stripe/webhook_test.rb +2 -2
  121. data/test/stripe_mock.rb +4 -3
  122. data/test/stripe_test.rb +0 -13
  123. data/test/test_helper.rb +10 -5
  124. metadata +11 -39
  125. data/lib/stripe/resources/issuer_fraud_record.rb +0 -9
  126. data/test/stripe/file_upload_test.rb +0 -79
  127. data/test/stripe/issuer_fraud_record_test.rb +0 -20
  128. data/test/stripe/usage_record_test.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b2abaedad94afb640e2ee4b39c6a825a2aa8f234d8ce5d64542d73cae0c46c92
4
- data.tar.gz: c5c0f7c81270700f7abbf8adcf329268daaff092c8c4892c500ff06c6a1e2dc4
3
+ metadata.gz: fa015ad0ee6a063db43580f0234ec2738fe5670c82cfa4843ed3bc91d8eb4670
4
+ data.tar.gz: f987cba3323dbac56c0121fd0d89d5c282a2b3cab9d46f9284cae99b0093d534
5
5
  SHA512:
6
- metadata.gz: 4f3955ca4759861c3f5d2bd6c78d661239886e44d3cf25939185dc0cc1846ded39c19c71f15c1c71295d686d2cab2d3b5937c11cf0dc9364dbca9289718f02b7
7
- data.tar.gz: 9d3d78053ccb35930ebf2cb7da3b4fe986e357599d53fe685b63f79799e26707354eac68b8ce70b0958ddce0375865f67158c1c843c7bd74d28f4b8f8fd3a56c
6
+ metadata.gz: 9b5d25d67c8ade84275d3187988de8660df98d1b2323fa231bc4e1a5ef6dfc9edb2ffcbe71bff404f7a473f4cdde0c5644ec379c625f9a45ea62606792f29871
7
+ data.tar.gz: ede395b847a59fba4fc3200f174d212c79fa0781222def2323d27cfdec626f3ff869147c2dfc3639206ce9b4d5ff0a282ec92059d04b8ff6b26d619d81655acd
@@ -2,21 +2,31 @@ inherit_from: .rubocop_todo.yml
2
2
 
3
3
  AllCops:
4
4
  DisplayCopNames: true
5
- TargetRubyVersion: 2.1
5
+ TargetRubyVersion: 2.3
6
6
 
7
7
  Layout/CaseIndentation:
8
8
  EnforcedStyle: end
9
9
 
10
- Layout/IndentArray:
10
+ Layout/IndentFirstArrayElement:
11
11
  EnforcedStyle: consistent
12
12
 
13
- Layout/IndentHash:
13
+ Layout/IndentFirstHashElement:
14
14
  EnforcedStyle: consistent
15
15
 
16
- Metrics/LineLength:
16
+ # This can be re-enabled once we're 2.3+ only and can use the squiggly heredoc
17
+ # operator. Prior to that, Rubocop recommended bringing in a library like
18
+ # ActiveSupport to get heredoc indentation, which is just terrible.
19
+ Layout/IndentHeredoc:
20
+ Enabled: false
21
+
22
+ Metrics/ClassLength:
17
23
  Exclude:
18
24
  - "test/**/*.rb"
25
+
26
+ Metrics/LineLength:
27
+ Exclude:
19
28
  - "lib/stripe/resources/**/*.rb"
29
+ - "test/**/*.rb"
20
30
 
21
31
  Metrics/MethodLength:
22
32
  # There's ~2 long methods in `StripeClient`. If we want to truncate those a
@@ -33,6 +43,9 @@ Style/AccessModifierDeclarations:
33
43
  Style/FrozenStringLiteralComment:
34
44
  EnforcedStyle: always
35
45
 
46
+ Style/NumericPredicate:
47
+ Enabled: false
48
+
36
49
  Style/StringLiterals:
37
50
  EnforcedStyle: double_quotes
38
51
 
@@ -1,24 +1,25 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-05-24 10:18:48 -0700 using RuboCop version 0.57.2.
3
+ # on 2019-07-30 09:56:31 +0800 using RuboCop version 0.73.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 20
9
+ # Offense count: 23
10
10
  Metrics/AbcSize:
11
- Max: 53
11
+ Max: 51
12
12
 
13
- # Offense count: 31
13
+ # Offense count: 33
14
14
  # Configuration parameters: CountComments, ExcludedMethods.
15
+ # ExcludedMethods: refine
15
16
  Metrics/BlockLength:
16
- Max: 498
17
+ Max: 509
17
18
 
18
- # Offense count: 11
19
+ # Offense count: 12
19
20
  # Configuration parameters: CountComments.
20
21
  Metrics/ClassLength:
21
- Max: 673
22
+ Max: 694
22
23
 
23
24
  # Offense count: 12
24
25
  Metrics/CyclomaticComplexity:
@@ -29,10 +30,10 @@ Metrics/CyclomaticComplexity:
29
30
  Metrics/ParameterLists:
30
31
  Max: 7
31
32
 
32
- # Offense count: 7
33
+ # Offense count: 8
33
34
  Metrics/PerceivedComplexity:
34
35
  Max: 17
35
36
 
36
- # Offense count: 84
37
+ # Offense count: 86
37
38
  Style/Documentation:
38
39
  Enabled: false
@@ -1,13 +1,11 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 2.1
5
- - 2.2
6
4
  - 2.3
7
5
  - 2.4
8
6
  - 2.5
9
7
  - 2.6
10
- - jruby-9.0.5.0
8
+ - jruby-9.2.7.0
11
9
 
12
10
  notifications:
13
11
  email:
@@ -25,8 +23,6 @@ cache:
25
23
  - stripe-mock
26
24
 
27
25
  before_install:
28
- # Install bundler 1.x, because we need to support Ruby 2.1 for now
29
- - gem install bundler -v "~> 1.0"
30
26
  # Unpack and start stripe-mock so that the test suite can talk to it
31
27
  - |
32
28
  if [ ! -d "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}" ]; then
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.0.0 - 2019-08-20
4
+ Major version release. The [migration guide](https://github.com/stripe/stripe-ruby/wiki/Migration-guide-for-v5) contains a detailed list of backwards-incompatible changes with upgrade instructions.
5
+
6
+ Pull requests included in this release (cf. [#815](https://github.com/stripe/stripe-ruby/pull/815)) (⚠️ = breaking changes):
7
+ * [x] ⚠️ #813: Convert library to use built-in `Net::HTTP`
8
+ * [x] ⚠️ #816: Make `code` argument in `CardError` named instead of positional.
9
+ * [x] ⚠️ #817: Drop support for very old Ruby versions.
10
+ * [x] #818: Bump Rubocop to latest version
11
+ * [x] #819: Ruby minimum version increase followup
12
+ * [x] ⚠️ #820: Remove old deprecated methods
13
+ * [x] ⚠️ #823: Remove all alias for list methods
14
+ * [x] ⚠️ #826: Remove `UsageRecord.create` method
15
+ * [x] ⚠️ #827: Remove `IssuerFraudRecord`
16
+ * [x] #811: Add `ErrorObject` to `StripeError` exceptions
17
+ * [x] #828: Tweak retry logic to be a little more like stripe-node
18
+ * [x] #829: Reset connections when connection-changing configuration changes (optional)
19
+ * [x] #830: Fix inverted sign for 500 retries
20
+ * [x] ⚠️#831: Remove a few more very old deprecated methods
21
+ * [x] #832: Minor cleanup in `StripeClient`
22
+ * [x] #833: Do better bookkeeping when tracking state in `Thread.current`
23
+ * [x] #834: Add `Invoice.list_upcoming_line_items` method
24
+
3
25
  ## 4.24.0 - 2019-08-12
4
26
  * [#825](https://github.com/stripe/stripe-ruby/pull/825) Add `SubscriptionItem.create_usage_record` method
5
27
  - This release also removed the `SubscriptionSchedule.revisions` method. This should have been included in the previous release (4.23.0)
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ gemspec
7
7
  group :development do
8
8
  gem "coveralls", require: false
9
9
  gem "mocha", "~> 0.13.2"
10
+ gem "rack", ">= 2.0.6"
10
11
  gem "rake"
11
12
  gem "shoulda-context"
12
13
  gem "test-unit"
@@ -18,18 +19,7 @@ group :development do
18
19
  # `Gemfile.lock` checked in, so to prevent good builds from suddenly going
19
20
  # bad, pin to a specific version number here. Try to keep this relatively
20
21
  # up-to-date, but it's not the end of the world if it's not.
21
- # Note that 0.57.2 is the most recent version we can use until we drop
22
- # support for Ruby 2.1.
23
- gem "rubocop", "0.57.2"
24
-
25
- # Rack 2.0+ requires Ruby >= 2.2.2 which is problematic for the test suite on
26
- # older Ruby versions. Check Ruby the version here and put a maximum
27
- # constraint on Rack if necessary.
28
- if RUBY_VERSION >= "2.2.2"
29
- gem "rack", ">= 2.0.6"
30
- else
31
- gem "rack", ">= 1.6.11", "< 2.0" # rubocop:disable Bundler/DuplicatedGem
32
- end
22
+ gem "rubocop", "0.73"
33
23
 
34
24
  platforms :mri do
35
25
  gem "byebug"
data/README.md CHANGED
@@ -39,7 +39,7 @@ gem build stripe.gemspec
39
39
 
40
40
  ### Requirements
41
41
 
42
- - Ruby 2.1+.
42
+ - Ruby 2.3+.
43
43
 
44
44
  ### Bundler
45
45
 
@@ -112,15 +112,13 @@ Stripe::Charge.retrieve(
112
112
  )
113
113
  ```
114
114
 
115
- ### Configuring a Client
115
+ ### Accessing a response object
116
116
 
117
- While a default HTTP client is used by default, it's also possible to have the
118
- library use any client supported by [Faraday][faraday] by initializing a
119
- `Stripe::StripeClient` object and giving it a connection:
117
+ Get access to response objects by initializing a client and using its `request`
118
+ method:
120
119
 
121
120
  ```ruby
122
- conn = Faraday.new
123
- client = Stripe::StripeClient.new(conn)
121
+ client = Stripe::StripeClient.new
124
122
  charge, resp = client.request do
125
123
  Stripe::Charge.retrieve(
126
124
  "ch_18atAXCdGbJFKhCuBAa4532Z",
@@ -159,13 +157,16 @@ Stripe.ca_bundle_path = "path/to/ca/bundle"
159
157
 
160
158
  ### Configuring Automatic Retries
161
159
 
162
- The library can be configured to automatically retry requests that fail due to
163
- an intermittent network problem:
160
+ You can enable automatic retries on requests that fail due to a transient
161
+ problem by configuring the maximum number of retries:
164
162
 
165
163
  ```ruby
166
164
  Stripe.max_network_retries = 2
167
165
  ```
168
166
 
167
+ Various errors can trigger a retry, like a connection error or a timeout, and
168
+ also certain API responses like HTTP status `409 Conflict`.
169
+
169
170
  [Idempotency keys][idempotency-keys] are added to requests to guarantee that
170
171
  retries are safe.
171
172
 
@@ -272,7 +273,6 @@ Update the bundled [stripe-mock] by editing the version number found in
272
273
  [api-keys]: https://dashboard.stripe.com/account/apikeys
273
274
  [connect]: https://stripe.com/connect
274
275
  [curl]: http://curl.haxx.se/docs/caextract.html
275
- [faraday]: https://github.com/lostisland/faraday
276
276
  [idempotency-keys]: https://stripe.com/docs/api/ruby#idempotent_requests
277
277
  [stripe-mock]: https://github.com/stripe/stripe-mock
278
278
  [versioning]: https://stripe.com/docs/api/ruby#versioning
data/Rakefile CHANGED
@@ -13,7 +13,8 @@ RuboCop::RakeTask.new
13
13
 
14
14
  desc "Update bundled certs"
15
15
  task :update_certs do
16
- require "faraday"
16
+ require "net/http"
17
+ require "uri"
17
18
 
18
19
  fetch_file "https://curl.haxx.se/ca/cacert.pem",
19
20
  ::File.expand_path("../lib/data/ca-certificates.crt", __FILE__)
@@ -23,14 +24,14 @@ end
23
24
  # helpers
24
25
  #
25
26
 
26
- def fetch_file(url, dest)
27
+ def fetch_file(uri, dest)
27
28
  ::File.open(dest, "w") do |file|
28
- resp = Faraday.get(url)
29
- unless resp.status == 200
30
- abort("bad response when fetching: #{url}\n" \
31
- "Status #{resp.status}: #{resp.body}")
29
+ resp = Net::HTTP.get_response(URI.parse(uri))
30
+ unless resp.code.to_i == 200
31
+ abort("bad response when fetching: #{uri}\n" \
32
+ "Status #{resp.code}: #{resp.body}")
32
33
  end
33
34
  file.write(resp.body)
34
- puts "Successfully fetched: #{url}"
35
+ puts "Successfully fetched: #{uri}"
35
36
  end
36
37
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.24.0
1
+ 5.0.0
@@ -3,9 +3,9 @@
3
3
  # Stripe Ruby bindings
4
4
  # API spec at https://stripe.com/docs/api
5
5
  require "cgi"
6
- require "faraday"
7
6
  require "json"
8
7
  require "logger"
8
+ require "net/http"
9
9
  require "openssl"
10
10
  require "rbconfig"
11
11
  require "securerandom"
@@ -28,10 +28,13 @@ require "stripe/api_operations/save"
28
28
  require "stripe/errors"
29
29
  require "stripe/object_types"
30
30
  require "stripe/util"
31
+ require "stripe/connection_manager"
32
+ require "stripe/multipart_encoder"
31
33
  require "stripe/stripe_client"
32
34
  require "stripe/stripe_object"
33
35
  require "stripe/stripe_response"
34
36
  require "stripe/list_object"
37
+ require "stripe/error_object"
35
38
  require "stripe/api_resource"
36
39
  require "stripe/singleton_api_resource"
37
40
  require "stripe/webhook"
@@ -70,9 +73,20 @@ module Stripe
70
73
  @enable_telemetry = true
71
74
 
72
75
  class << self
73
- attr_accessor :stripe_account, :api_key, :api_base, :verify_ssl_certs,
74
- :api_version, :client_id, :connect_base, :uploads_base,
75
- :open_timeout, :read_timeout, :proxy
76
+ attr_accessor :api_key
77
+ attr_accessor :api_version
78
+ attr_accessor :client_id
79
+ attr_accessor :stripe_account
80
+
81
+ # These all get manual attribute writers so that we can reset connections
82
+ # if they change.
83
+ attr_reader :api_base
84
+ attr_reader :connect_base
85
+ attr_reader :open_timeout
86
+ attr_reader :proxy
87
+ attr_reader :read_timeout
88
+ attr_reader :uploads_base
89
+ attr_reader :verify_ssl_certs
76
90
 
77
91
  attr_reader :max_network_retry_delay, :initial_network_retry_delay
78
92
  end
@@ -87,6 +101,11 @@ module Stripe
87
101
  @app_info = info
88
102
  end
89
103
 
104
+ def self.api_base=(api_base)
105
+ @api_base = api_base
106
+ StripeClient.clear_all_connection_managers
107
+ end
108
+
90
109
  # The location of a file containing a bundle of CA certificates. By default
91
110
  # the library will use an included bundle that can successfully validate
92
111
  # Stripe certificates.
@@ -99,6 +118,8 @@ module Stripe
99
118
 
100
119
  # empty this field so a new store is initialized
101
120
  @ca_store = nil
121
+
122
+ StripeClient.clear_all_connection_managers
102
123
  end
103
124
 
104
125
  # A certificate store initialized from the the bundle in #ca_bundle_path and
@@ -118,6 +139,19 @@ module Stripe
118
139
  end
119
140
  end
120
141
 
142
+ def self.connection_base=(connection_base)
143
+ @connection_base = connection_base
144
+ StripeClient.clear_all_connection_managers
145
+ end
146
+
147
+ def self.enable_telemetry?
148
+ @enable_telemetry
149
+ end
150
+
151
+ def self.enable_telemetry=(val)
152
+ @enable_telemetry = val
153
+ end
154
+
121
155
  # map to the same values as the standard library's logger
122
156
  LEVEL_DEBUG = Logger::DEBUG
123
157
  LEVEL_ERROR = Logger::ERROR
@@ -172,12 +206,19 @@ module Stripe
172
206
  @max_network_retries = val.to_i
173
207
  end
174
208
 
175
- def self.enable_telemetry?
176
- @enable_telemetry
209
+ def self.open_timeout=(open_timeout)
210
+ @open_timeout = open_timeout
211
+ StripeClient.clear_all_connection_managers
177
212
  end
178
213
 
179
- def self.enable_telemetry=(val)
180
- @enable_telemetry = val
214
+ def self.proxy=(proxy)
215
+ @proxy = proxy
216
+ StripeClient.clear_all_connection_managers
217
+ end
218
+
219
+ def self.read_timeout=(read_timeout)
220
+ @read_timeout = read_timeout
221
+ StripeClient.clear_all_connection_managers
181
222
  end
182
223
 
183
224
  # Sets some basic information about the running application that's sent along
@@ -194,14 +235,14 @@ module Stripe
194
235
  }
195
236
  end
196
237
 
197
- # DEPRECATED. Use `Util#encode_parameters` instead.
198
- def self.uri_encode(params)
199
- Util.encode_parameters(params)
238
+ def self.uploads_base=(uploads_base)
239
+ @uploads_base = uploads_base
240
+ StripeClient.clear_all_connection_managers
200
241
  end
201
- private_class_method :uri_encode
202
- class << self
203
- extend Gem::Deprecate
204
- deprecate :uri_encode, "Stripe::Util#encode_parameters", 2016, 1
242
+
243
+ def self.verify_ssl_certs=(verify_ssl_certs)
244
+ @verify_ssl_certs = verify_ssl_certs
245
+ StripeClient.clear_all_connection_managers
205
246
  end
206
247
  end
207
248
 
@@ -19,12 +19,6 @@ module Stripe
19
19
 
20
20
  obj
21
21
  end
22
-
23
- # The original version of #list was given the somewhat unfortunate name of
24
- # #all, and this alias allows us to maintain backward compatibility (the
25
- # choice was somewhat misleading in the way that it only returned a single
26
- # page rather than all objects).
27
- alias all list
28
22
  end
29
23
  end
30
24
  end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Stripe
4
+ # Manages connections across multiple hosts which is useful because the
5
+ # library may connect to multiple hosts during a typical session (main API,
6
+ # Connect, Uploads). Ruby doesn't provide an easy way to make this happen
7
+ # easily, so this class is designed to track what we're connected to and
8
+ # manage the lifecycle of those connections.
9
+ #
10
+ # Note that this class in itself is *not* thread safe. We expect it to be
11
+ # instantiated once per thread.
12
+ #
13
+ # Note also that this class doesn't currently clean up after itself because
14
+ # it expects to only ever have a few connections. It'd be possible to tank
15
+ # memory by constantly changing the value of `Stripe.api_base` or the like. A
16
+ # possible improvement might be to detect and prune old connections whenever
17
+ # a request is executed.
18
+ class ConnectionManager
19
+ def initialize
20
+ @active_connections = {}
21
+ end
22
+
23
+ # Finishes any active connections by closing their TCP connection and
24
+ # clears them from internal tracking.
25
+ def clear
26
+ @active_connections.each do |_, connection|
27
+ connection.finish
28
+ end
29
+ @active_connections = {}
30
+ end
31
+
32
+ # Gets a connection for a given URI. This is for internal use only as it's
33
+ # subject to change (we've moved between HTTP client schemes in the past
34
+ # and may do it again).
35
+ #
36
+ # `uri` is expected to be a string.
37
+ def connection_for(uri)
38
+ u = URI.parse(uri)
39
+ connection = @active_connections[[u.host, u.port]]
40
+
41
+ if connection.nil?
42
+ connection = create_connection(u)
43
+
44
+ # TODO: what happens after TTL?
45
+ connection.start
46
+
47
+ @active_connections[[u.host, u.port]] = connection
48
+ end
49
+
50
+ connection
51
+ end
52
+
53
+ # Executes an HTTP request to the given URI with the given method. Also
54
+ # allows a request body, headers, and query string to be specified.
55
+ def execute_request(method, uri, body: nil, headers: nil, query: nil)
56
+ # Perform some basic argument validation because it's easy to get
57
+ # confused between strings and hashes for things like body and query
58
+ # parameters.
59
+ raise ArgumentError, "method should be a symbol" \
60
+ unless method.is_a?(Symbol)
61
+ raise ArgumentError, "uri should be a string" \
62
+ unless uri.is_a?(String)
63
+ raise ArgumentError, "body should be a string" \
64
+ if body && !body.is_a?(String)
65
+ raise ArgumentError, "headers should be a hash" \
66
+ if headers && !headers.is_a?(Hash)
67
+ raise ArgumentError, "query should be a string" \
68
+ if query && !query.is_a?(String)
69
+
70
+ connection = connection_for(uri)
71
+
72
+ u = URI.parse(uri)
73
+ path = if query
74
+ u.path + "?" + query
75
+ else
76
+ u.path
77
+ end
78
+
79
+ connection.send_request(method.to_s.upcase, path, body, headers)
80
+ end
81
+
82
+ #
83
+ # private
84
+ #
85
+
86
+ # `uri` should be a parsed `URI` object.
87
+ private def create_connection(uri)
88
+ # These all come back as `nil` if no proxy is configured.
89
+ proxy_host, proxy_port, proxy_user, proxy_pass = proxy_parts
90
+
91
+ connection = Net::HTTP.new(uri.host, uri.port,
92
+ proxy_host, proxy_port,
93
+ proxy_user, proxy_pass)
94
+
95
+ connection.open_timeout = Stripe.open_timeout
96
+ connection.read_timeout = Stripe.read_timeout
97
+
98
+ connection.use_ssl = uri.scheme == "https"
99
+
100
+ if Stripe.verify_ssl_certs
101
+ connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
102
+ connection.cert_store = Stripe.ca_store
103
+ else
104
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
105
+
106
+ unless @verify_ssl_warned
107
+ @verify_ssl_warned = true
108
+ warn("WARNING: Running without SSL cert verification. " \
109
+ "You should never do this in production. " \
110
+ "Execute `Stripe.verify_ssl_certs = true` to enable " \
111
+ "verification.")
112
+ end
113
+ end
114
+
115
+ connection
116
+ end
117
+
118
+ # `Net::HTTP` somewhat awkwardly requires each component of a proxy URI
119
+ # (host, port, etc.) rather than the URI itself. This method simply parses
120
+ # out those pieces to make passing them into a new connection a little less
121
+ # ugly.
122
+ private def proxy_parts
123
+ if Stripe.proxy.nil?
124
+ [nil, nil, nil, nil]
125
+ else
126
+ u = URI.parse(Stripe.proxy)
127
+ [u.host, u.port, u.user, u.password]
128
+ end
129
+ end
130
+ end
131
+ end