Skip to content

Commit 92562e5

Browse files
authored
Merge pull request #334 from github/tonkpils/faraday2-dual-compat
Support Faraday 2 alongside 1.x
2 parents 129a930 + ec2061d commit 92562e5

10 files changed

Lines changed: 94 additions & 54 deletions

File tree

.github/workflows/main.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,20 @@ jobs:
1212
strategy:
1313
matrix:
1414
ruby-version: ['3.2']
15+
gemfile: ['faraday_1', 'faraday_2']
1516
ES_VERSION: ['8.18.0']
1617
include:
1718
- ES_VERSION: '8.18.0'
1819
ES_DOWNLOAD_URL: >-
1920
https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.18.0-linux-x86_64.tar.gz
21+
env:
22+
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
2023
steps:
24+
- uses: actions/checkout@v4
2125
- uses: ruby/setup-ruby@v1
2226
with:
2327
ruby-version: ${{ matrix.ruby-version }}
2428
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
25-
- uses: actions/checkout@v4
2629
- name: Cache Elasticsearch
2730
id: cache-elasticsearch
2831
uses: actions/cache@v4

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
/vendor/cache/*.gem
77
/coverage
88
Gemfile.lock
9+
gemfiles/*.lock
910
*.gem
1011
tags
1112
.byebug_history

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 6.3.0 (2026-06-22)
2+
- Add support for Faraday 2 (now compatible with both Faraday 1.x and 2.x)
3+
- Drop the deprecated `faraday_middleware` dependency in favor of `faraday-gzip`
4+
15
## 6.2.4 (2025-10-10)
26
- Added support for ES 8.19.3
37

Gemfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ group :development do
88
gem "activesupport", ">= 7.0"
99
gem "bundler", "~> 2.0"
1010
gem "debug", "~> 1.7"
11+
# The default bundle resolves Faraday 2.x, where the :retry middleware lives in the
12+
# faraday-retry gem (it is in core on 1.x). Needed for the retry test; consumers opt in.
13+
gem "faraday-retry", require: "faraday/retry"
1114
gem "minitest", "~> 5.17"
1215
gem "minitest-focus", "~> 1.3"
1316
gem "rake"
@@ -17,6 +20,5 @@ group :development do
1720
gem "rubocop-performance", "~> 1.21.0"
1821
gem "rubocop-rake", "~> 0.6.0"
1922
gem "simplecov", require: false
20-
gem "spy", "~> 1.0"
2123
gem "webmock", "~> 3.5"
2224
end

elastomer-client.gemspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ Gem::Specification.new do |spec|
2222
spec.require_paths = ["lib"]
2323

2424
spec.add_dependency "addressable", "~> 2.5"
25-
spec.add_dependency "faraday", ">= 0.17"
26-
spec.add_dependency "faraday_middleware", ">= 0.14"
25+
spec.add_dependency "faraday", ">= 1.0", "< 3"
26+
spec.add_dependency "faraday-gzip", ">= 1.0"
2727
spec.add_dependency "multi_json", "~> 1.12"
2828
spec.add_dependency "semantic", "~> 1.6"
2929
end

gemfiles/faraday_1.gemfile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# frozen_string_literal: true
2+
3+
# Tests elastomer-client against Faraday 1.x.
4+
#
5+
# faraday-gzip works on both Faraday 1.x and 2.x and provides the :gzip request middleware
6+
# used for response decompression (replacing the deprecated faraday_middleware).
7+
source "https://rubygems.org"
8+
9+
gem "faraday", "~> 1.10"
10+
11+
gemspec path: ".."
12+
13+
group :development do
14+
gem "activesupport", ">= 7.0"
15+
gem "bundler", "~> 2.0"
16+
gem "debug", "~> 1.7"
17+
gem "minitest", "~> 5.17"
18+
gem "minitest-focus", "~> 1.3"
19+
gem "rake"
20+
gem "rubocop", "~> 1.63.0"
21+
gem "rubocop-github", "~> 0.20.0"
22+
gem "rubocop-minitest", "~> 0.35.0"
23+
gem "rubocop-performance", "~> 1.21.0"
24+
gem "rubocop-rake", "~> 0.6.0"
25+
gem "simplecov", require: false
26+
gem "webmock", "~> 3.5"
27+
end

gemfiles/faraday_2.gemfile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# frozen_string_literal: true
2+
3+
# Tests elastomer-client against Faraday 2.x.
4+
#
5+
# This is the configuration the monolith targets after the Faraday 2 upgrade. faraday-gzip
6+
# provides the :gzip request middleware (response decompression) on Faraday 2.x.
7+
source "https://rubygems.org"
8+
9+
gem "faraday", "~> 2.0"
10+
11+
gemspec path: ".."
12+
13+
group :development do
14+
gem "activesupport", ">= 7.0"
15+
gem "bundler", "~> 2.0"
16+
gem "debug", "~> 1.7"
17+
# On Faraday 2.x the :retry middleware lives in the faraday-retry gem (it is in core on
18+
# 1.x). Consumers opt into retries via a connection block; the suite covers that path.
19+
gem "faraday-retry", require: "faraday/retry"
20+
gem "minitest", "~> 5.17"
21+
gem "minitest-focus", "~> 1.3"
22+
gem "rake"
23+
gem "rubocop", "~> 1.63.0"
24+
gem "rubocop-github", "~> 0.20.0"
25+
gem "rubocop-minitest", "~> 0.35.0"
26+
gem "rubocop-performance", "~> 1.21.0"
27+
gem "rubocop-rake", "~> 0.6.0"
28+
gem "simplecov", require: false
29+
gem "webmock", "~> 3.5"
30+
end

lib/elastomer_client/client.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
require "addressable/template"
44
require "faraday"
5-
require "faraday_middleware"
5+
require "faraday/gzip"
66
require "multi_json"
77
require "semantic"
88
require "zlib"
@@ -132,18 +132,22 @@ def connection
132132
@connection ||= Faraday.new(url) do |conn|
133133
conn.response(:parse_json)
134134
# Request compressed responses from ES and decompress them
135-
conn.use(:gzip)
135+
conn.request(:gzip)
136136
conn.request(:encode_json)
137137
conn.request(:limit_size, max_request_size:) if max_request_size
138138
conn.request(:elastomer_compress, compression:) if compress_body
139139

140140
conn.options[:timeout] = read_timeout
141141
conn.options[:open_timeout] = open_timeout
142142

143+
# Faraday 2 removed the Connection#token_auth and #basic_auth helpers, and the
144+
# :authorization middleware emits different header formats across Faraday majors.
145+
# Set the Authorization header directly so the output is identical on 1.x and 2.x.
143146
if token_auth?
144-
conn.token_auth(@token_auth)
147+
conn.headers["Authorization"] = %(Token token="#{@token_auth}")
145148
elsif basic_auth?
146-
conn.basic_auth(@basic_auth[:username], @basic_auth[:password])
149+
credentials = ["#{@basic_auth[:username]}:#{@basic_auth[:password]}"].pack("m0")
150+
conn.headers["Authorization"] = "Basic #{credentials}"
147151
end
148152

149153
@connection_block&.call(conn)

lib/elastomer_client/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
module ElastomerClient
4-
VERSION = "6.2.4"
4+
VERSION = "6.3.0"
55

66
def self.version
77
VERSION

test/client_test.rb

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313
end
1414

1515
it "allows configuring the Faraday when a block is given" do
16-
assert ElastomerClient::Client.new.connection.builder.handlers.none? { |handler| handler.klass == FaradayMiddleware::Instrumentation }
16+
assert ElastomerClient::Client.new.connection.builder.handlers.none? { |handler| handler.klass == ElastomerClient::Middleware::OpaqueId }
1717

1818
c = ElastomerClient::Client.new do |connection|
1919
assert_kind_of(Faraday::Connection, connection)
2020

21-
connection.use :instrumentation
21+
connection.request :opaque_id
2222
end
2323

24-
assert c.connection.builder.handlers.any? { |handler| handler.klass == FaradayMiddleware::Instrumentation }
24+
assert c.connection.builder.handlers.any? { |handler| handler.klass == ElastomerClient::Middleware::OpaqueId }
2525
end
2626

2727
it "use Faraday's default adapter if none is specified" do
@@ -145,14 +145,9 @@
145145
})
146146
client = ElastomerClient::Client.new(**client_params)
147147

148-
connection = Faraday::Connection.new
149-
basic_auth_spy = Spy.on(connection, :basic_auth).and_return(nil)
148+
expected = "Basic #{["my_user:my_secret_password"].pack("m0")}"
150149

151-
Faraday.stub(:new, $client_params[:url], connection) do
152-
client.ping
153-
end
154-
155-
assert basic_auth_spy.has_been_called_with?("my_user", "my_secret_password")
150+
assert_equal expected, client.connection.headers["Authorization"]
156151
end
157152

158153
it "ignores basic authentication if password is missing" do
@@ -161,14 +156,7 @@
161156
})
162157
client = ElastomerClient::Client.new(**client_params)
163158

164-
connection = Faraday::Connection.new
165-
basic_auth_spy = Spy.on(connection, :basic_auth).and_return(nil)
166-
167-
Faraday.stub(:new, $client_params[:url], connection) do
168-
client.ping
169-
end
170-
171-
refute_predicate basic_auth_spy, :has_been_called?
159+
refute client.connection.headers.key?("Authorization")
172160
end
173161

174162
it "ignores basic authentication if username is missing" do
@@ -177,28 +165,14 @@
177165
})
178166
client = ElastomerClient::Client.new(**client_params)
179167

180-
connection = Faraday::Connection.new
181-
basic_auth_spy = Spy.on(connection, :basic_auth).and_return(nil)
182-
183-
Faraday.stub(:new, $client_params[:url], connection) do
184-
client.ping
185-
end
186-
187-
refute_predicate basic_auth_spy, :has_been_called?
168+
refute client.connection.headers.key?("Authorization")
188169
end
189170

190171
it "can use token authentication" do
191172
client_params = $client_params.merge(token_auth: "my_secret_token")
192173
client = ElastomerClient::Client.new(**client_params)
193174

194-
connection = Faraday::Connection.new
195-
token_auth_spy = Spy.on(connection, :token_auth).and_return(nil)
196-
197-
Faraday.stub(:new, $client_params[:url], connection) do
198-
client.ping
199-
end
200-
201-
assert token_auth_spy.has_been_called_with?("my_secret_token")
175+
assert_equal %(Token token="my_secret_token"), client.connection.headers["Authorization"]
202176
end
203177

204178
it "prefers token authentication over basic" do
@@ -208,16 +182,7 @@
208182
}, token_auth: "my_secret_token")
209183
client = ElastomerClient::Client.new(**client_params)
210184

211-
connection = Faraday::Connection.new
212-
basic_auth_spy = Spy.on(connection, :basic_auth).and_return(nil)
213-
token_auth_spy = Spy.on(connection, :token_auth).and_return(nil)
214-
215-
Faraday.stub(:new, $client_params[:url], connection) do
216-
client.ping
217-
end
218-
219-
refute_predicate basic_auth_spy, :has_been_called?
220-
assert token_auth_spy.has_been_called_with?("my_secret_token")
185+
assert_equal %(Token token="my_secret_token"), client.connection.headers["Authorization"]
221186
end
222187
end
223188

@@ -372,11 +337,15 @@
372337
it "adding retry logic retries up to 2 times" do
373338
retry_count = 0
374339

340+
# :retry maps to Faraday::Request::Retry on Faraday 1.x and Faraday::Retry::Middleware
341+
# on Faraday 2.x (via faraday-retry). Look up whichever the running Faraday registers.
342+
retry_klass = Faraday::Request.lookup_middleware(:retry)
343+
375344
retry_options = {
376345
max: 2,
377346
interval: 0.05,
378347
methods: [:get],
379-
exceptions: Faraday::Request::Retry::DEFAULT_EXCEPTIONS + [Faraday::ConnectionFailed],
348+
exceptions: retry_klass::DEFAULT_EXCEPTIONS + [Faraday::ConnectionFailed],
380349
retry_block: proc { |env, options, retries, exc| retry_count += 1 }
381350
}
382351
retry_client = ElastomerClient::Client.new(port: 9205) do |connection|

0 commit comments

Comments
 (0)