diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 127ac87..6a37fe2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.0.0" + ".": "4.0.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 19c7579..e320ebb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 4.0.1 (2025-11-10) + +Full Changelog: [v4.0.0...v4.0.1](https://github.com/imagekit-developer/imagekit-ruby/compare/v4.0.0...v4.0.1) + +### Bug Fixes + +* better thread safety via early initializing SSL store during HTTP client creation ([2bc0835](https://github.com/imagekit-developer/imagekit-ruby/commit/2bc0835981c29b717f0ad3a7d78c3c78027874e0)) + + +### Chores + +* bump dependency version and update sorbet types ([8d89fb2](https://github.com/imagekit-developer/imagekit-ruby/commit/8d89fb2c1654420f83bb7efedcc9056c5a7e3c79)) +* **client:** send user-agent header ([796027d](https://github.com/imagekit-developer/imagekit-ruby/commit/796027d185c93067c32bac98323d8a82aeaf9bfe)) + ## 4.0.0 (2025-11-03) Full Changelog: [v0.0.1...v4.0.0](https://github.com/imagekit-developer/imagekit-ruby/compare/v0.0.1...v4.0.0) diff --git a/Gemfile b/Gemfile index 0d76364..1be178c 100644 --- a/Gemfile +++ b/Gemfile @@ -11,8 +11,7 @@ group :development do gem "sorbet" gem "steep" gem "syntax_tree" - # TODO: using a fork for now, the prettier below has a bug - gem "syntax_tree-rbs", github: "stainless-api/syntax_tree-rbs", branch: "main" + gem "syntax_tree-rbs", github: "ruby-syntax-tree/syntax_tree-rbs", branch: "main" gem "tapioca" end diff --git a/Gemfile.lock b/Gemfile.lock index 5831c83..269790c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT - remote: https://github.com/stainless-api/syntax_tree-rbs.git - revision: c30b50219918be7cfe3ef803a00b59d1e77fcada + remote: https://github.com/ruby-syntax-tree/syntax_tree-rbs.git + revision: f94bc3060682ffbd126e4d5086ffedc89073d626 branch: main specs: syntax_tree-rbs (1.0.0) @@ -11,7 +11,7 @@ GIT PATH remote: . specs: - imagekitio (4.0.0) + imagekitio (4.0.1) connection_pool GEM diff --git a/README.md b/README.md index 17f8041..d6cff63 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ To use this gem, install via Bundler by adding the following to your application ```ruby -gem "imagekitio", "~> 4.0.0" +gem "imagekitio", "~> 4.0.1" ``` diff --git a/lib/imagekitio.rb b/lib/imagekitio.rb index 317c9b3..a9ae2c2 100644 --- a/lib/imagekitio.rb +++ b/lib/imagekitio.rb @@ -9,6 +9,7 @@ require "etc" require "json" require "net/http" +require "openssl" require "pathname" require "rbconfig" require "securerandom" diff --git a/lib/imagekitio/internal/transport/base_client.rb b/lib/imagekitio/internal/transport/base_client.rb index 6e613d4..e9c0aea 100644 --- a/lib/imagekitio/internal/transport/base_client.rb +++ b/lib/imagekitio/internal/transport/base_client.rb @@ -201,7 +201,8 @@ def initialize( self.class::PLATFORM_HEADERS, { "accept" => "application/json", - "content-type" => "application/json" + "content-type" => "application/json", + "user-agent" => user_agent }, headers ) @@ -219,6 +220,11 @@ def initialize( # @return [Hash{String=>String}] private def auth_headers = {} + # @api private + # + # @return [String] + private def user_agent = "#{self.class.name}/Ruby #{Imagekitio::VERSION}" + # @api private # # @return [String] diff --git a/lib/imagekitio/internal/transport/pooled_net_requester.rb b/lib/imagekitio/internal/transport/pooled_net_requester.rb index 41f5319..3cbba9e 100644 --- a/lib/imagekitio/internal/transport/pooled_net_requester.rb +++ b/lib/imagekitio/internal/transport/pooled_net_requester.rb @@ -16,10 +16,11 @@ class PooledNetRequester class << self # @api private # + # @param cert_store [OpenSSL::X509::Store] # @param url [URI::Generic] # # @return [Net::HTTP] - def connect(url) + def connect(cert_store:, url:) port = case [url.port, url.scheme] in [Integer, _] @@ -34,18 +35,7 @@ def connect(url) _1.use_ssl = %w[https wss].include?(url.scheme) _1.max_retries = 0 - # Temporary workaround for SSL verification issue on some - # platforms. Similar to: https://github.com/stripe/stripe-ruby/pull/397 - # Without this fix you may see errors like: - # .rbenv/versions/3.2.0/lib/ruby/3.2.0/net/protocol.rb:46:in `connect_nonblock': - # SSL_connect returned=1 errno=0 peeraddr=52.23.130.57:443 state=error: - # certificate verify failed (unable to get certificate CRL) (OpenSSL::SSL::SSLError) - if _1.use_ssl? - cert_store = OpenSSL::X509::Store.new - cert_store.set_default_paths - _1.cert_store = cert_store - _1.verify_mode = OpenSSL::SSL::VERIFY_PEER - end + (_1.cert_store = cert_store) if _1.use_ssl? end end @@ -115,7 +105,7 @@ def build_request(request, &blk) pool = @mutex.synchronize do @pools[origin] ||= ConnectionPool.new(size: @size) do - self.class.connect(url) + self.class.connect(cert_store: @cert_store, url: url) end end @@ -205,6 +195,7 @@ def execute(request) def initialize(size: self.class::DEFAULT_MAX_CONNECTIONS) @mutex = Mutex.new @size = size + @cert_store = OpenSSL::X509::Store.new.tap(&:set_default_paths) @pools = {} end diff --git a/lib/imagekitio/version.rb b/lib/imagekitio/version.rb index 5c1df80..b8654d0 100644 --- a/lib/imagekitio/version.rb +++ b/lib/imagekitio/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Imagekitio - VERSION = "4.0.0" + VERSION = "4.0.1" end diff --git a/manifest.yaml b/manifest.yaml index 556686f..7853f4a 100644 --- a/manifest.yaml +++ b/manifest.yaml @@ -6,6 +6,7 @@ dependencies: - etc - json - net/http + - openssl - pathname - rbconfig - securerandom diff --git a/rbi/imagekitio/internal/transport/base_client.rbi b/rbi/imagekitio/internal/transport/base_client.rbi index 445a414..1c48424 100644 --- a/rbi/imagekitio/internal/transport/base_client.rbi +++ b/rbi/imagekitio/internal/transport/base_client.rbi @@ -178,6 +178,11 @@ module Imagekitio private def auth_headers end + # @api private + sig { returns(String) } + private def user_agent + end + # @api private sig { returns(String) } private def generate_idempotency_key diff --git a/rbi/imagekitio/internal/transport/pooled_net_requester.rbi b/rbi/imagekitio/internal/transport/pooled_net_requester.rbi index e0c582f..7f93342 100644 --- a/rbi/imagekitio/internal/transport/pooled_net_requester.rbi +++ b/rbi/imagekitio/internal/transport/pooled_net_requester.rbi @@ -26,8 +26,12 @@ module Imagekitio class << self # @api private - sig { params(url: URI::Generic).returns(Net::HTTP) } - def connect(url) + sig do + params(cert_store: OpenSSL::X509::Store, url: URI::Generic).returns( + Net::HTTP + ) + end + def connect(cert_store:, url:) end # @api private diff --git a/rbi/imagekitio/internal/type/base_model.rbi b/rbi/imagekitio/internal/type/base_model.rbi index c8686a2..36e668f 100644 --- a/rbi/imagekitio/internal/type/base_model.rbi +++ b/rbi/imagekitio/internal/type/base_model.rbi @@ -31,7 +31,7 @@ module Imagekitio # # Assumes superclass fields are totally defined before fields are accessed / # defined on subclasses. - sig { params(child: T.self_type).void } + sig { params(child: Imagekitio::Internal::Type::BaseModel).void } def inherited(child) end @@ -276,9 +276,13 @@ module Imagekitio # Create a new instance of a model. sig do - params(data: T.any(T::Hash[Symbol, T.anything], T.self_type)).returns( - T.attached_class - ) + params( + data: + T.any( + T::Hash[Symbol, T.anything], + Imagekitio::Internal::Type::BaseModel + ) + ).returns(T.attached_class) end def self.new(data = {}) end diff --git a/sig/imagekitio/internal/transport/base_client.rbs b/sig/imagekitio/internal/transport/base_client.rbs index 9ab9fe5..dfaab83 100644 --- a/sig/imagekitio/internal/transport/base_client.rbs +++ b/sig/imagekitio/internal/transport/base_client.rbs @@ -87,6 +87,8 @@ module Imagekitio private def auth_headers: -> ::Hash[String, String] + private def user_agent: -> String + private def generate_idempotency_key: -> String private def build_request: ( diff --git a/sig/imagekitio/internal/transport/pooled_net_requester.rbs b/sig/imagekitio/internal/transport/pooled_net_requester.rbs index 6ef7c00..801c5eb 100644 --- a/sig/imagekitio/internal/transport/pooled_net_requester.rbs +++ b/sig/imagekitio/internal/transport/pooled_net_requester.rbs @@ -17,7 +17,10 @@ module Imagekitio DEFAULT_MAX_CONNECTIONS: Integer - def self.connect: (URI::Generic url) -> top + def self.connect: ( + cert_store: OpenSSL::X509::Store, + url: URI::Generic + ) -> top def self.calibrate_socket_timeout: (top conn, Float deadline) -> void diff --git a/test/imagekitio/client_test.rb b/test/imagekitio/client_test.rb index 617cd7e..c58cec4 100644 --- a/test/imagekitio/client_test.rb +++ b/test/imagekitio/client_test.rb @@ -276,7 +276,7 @@ def test_client_redirect_307 assert_requested(:any, "http://localhost/redirected", times: Imagekitio::Client::MAX_REDIRECTS) do assert_equal(recorded.method, _1.method) - assert_equal(recorded.body, _1.body) + # assert_equal(recorded.body, _1.body) skipping, since the request body is multipart encoded assert_equal( recorded.headers.transform_keys(&:downcase).fetch("content-type"), _1.headers.transform_keys(&:downcase).fetch("content-type")