Begin v2 release (#1297)

* Update UPGRADING.md to highlight adapters being moved out
* Cleanup tests
* Cleanup Gemfile
* Update CI
This commit is contained in:
Matt 2021-08-01 17:09:03 +01:00 committed by GitHub
parent a089fb83fa
commit 6333b73d13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 68 additions and 418 deletions

View File

@ -4,7 +4,7 @@ on:
pull_request:
push:
branches: [main, 0.1x]
branches: [main, 1.x, 0.1x]
env:
GIT_COMMIT_SHA: ${{ github.sha }}
@ -14,27 +14,24 @@ env:
jobs:
linting:
runs-on: ubuntu-latest
env:
BUNDLE_WITH: lint
BUNDLE_WITHOUT: development:test
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Set up Ruby 2.7
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
bundler-cache: true
- name: Rubocop
run: |
gem install bundler
bundle config set without 'development test'
bundle config set with 'lint'
bundle install
bundle exec rubocop --format progress
run: bundle exec rubocop --format progress
- name: Yard-Junk
run: |
gem install yard-junk --no-document
yard-junk --path lib
run: bundle exec yard-junk --path lib
build:
needs: [linting]
@ -43,22 +40,14 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby: ['2.4', '2.5', '2.6', '2.7', '3.0']
ruby: ['2.6', '2.7', '3.0']
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- name: Install dependencies
run: |
sudo apt-get install libcurl4-openssl-dev
- name: Build
run: |
gem install bundler -v '<2'
bundle install --jobs 4 --retry 3
bundler-cache: true
- name: Test
continue-on-error: ${{ matrix.experimental }}

View File

@ -10,20 +10,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/checkout@v2
- name: Set up Ruby 2.6
- name: Set up Ruby 2.7
uses: actions/setup-ruby@v1
with:
ruby-version: 2.6.x
ruby-version: 2.7
- name: Publish to RubyGems
run: |
mkdir -p $HOME/.gem
touch $HOME/.gem/credentials
chmod 0600 $HOME/.gem/credentials
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
gem build faraday.gemspec
gem push faraday-*.gem
env:
GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_AUTH_TOKEN }}
uses: dawidd6/action-publish-gem@v1
with:
api_key: ${{secrets.RUBYGEMS_AUTH_TOKEN}}

33
Gemfile
View File

@ -2,39 +2,28 @@
source 'https://rubygems.org'
ruby RUBY_VERSION
# Even though we don't officially support JRuby, this dependency makes Faraday
# compatible with it, so we're leaving it in for jruby users to use it.
gem 'jruby-openssl', '~> 0.10.7', platforms: :jruby
group :development, :test do
gem 'coveralls_reborn', require: false
gem 'multipart-parser'
gem 'pry'
gem 'rack', '~> 2.2'
gem 'rake'
gem 'rspec', '~> 3.7'
gem 'rspec_junit_formatter', '~> 0.4'
gem 'simplecov'
gem 'webmock', '~> 3.4'
end
group :lint, :development do
group :development, :lint do
gem 'rubocop', '~> 0.90.0'
gem 'rubocop-inclusivity', '~> 1.0'
gem 'rubocop-packaging', '~> 0.5'
gem 'rubocop-performance', '~> 1.0'
end
group :test, :development do
gem 'coveralls_reborn', require: false
gem 'em-http-request', '>= 1.1', require: 'em-http', platform: :ruby
gem 'em-synchrony', '>= 1.0.3', require: %w[em-synchrony em-synchrony/em-http], platform: :ruby
gem 'excon', '>= 0.27.4'
gem 'httpclient', '>= 2.2'
gem 'multipart-parser'
# TODO: remove this once v4 is released
options = (RUBY_VERSION.start_with?('3') ? { github: 'grosser/net-http-persistent', branch: 'grosser/spec' } : {})
gem 'net-http-persistent', '>= 3.0', **options
gem 'patron', '>= 0.4.2', platforms: :ruby
gem 'rack-test', '>= 0.6', require: 'rack/test'
gem 'rspec', '~> 3.7'
gem 'rspec_junit_formatter', '~> 0.4'
gem 'simplecov'
gem 'typhoeus', '~> 1.4'
gem 'webmock', '~> 3.4'
gem 'yard-junk'
end
gemspec

View File

@ -16,10 +16,10 @@ Need more details? See the [Faraday API Documentation][apidoc] to see how it wor
## Supported Ruby versions
This library aims to support and is [tested against][actions] the following Ruby
implementations:
* Ruby 2.4+
This library aims to support and is [tested against][actions] the currently officially supported Ruby
implementations. This means that, even without a major release, we could add or drop support for Ruby versions,
following their [EOL](https://endoflife.date/ruby).
Currently that means we support Ruby 2.6+
If something doesn't work on one of these Ruby versions, it's a bug.

View File

@ -1,6 +1,38 @@
## Faraday 2.0
### Adapters have moved!
With this release, we've officially moved all adapters out of Faraday.
What that means, is that they won't be available out-of-the-box anymore,
and you'll instead need to add them to your Gemfile.
#### Why was this decision made?
We've taken this decision for the following technical reasons:
* We wanted the Faraday gem to focus on providing a clean, standardized, middleware-stack-based API.
* We wanted to free the core team from maintaining all the different adapters, relying more on the community to
maintain them based on the broad interest. This will allow the core team to focus on implementing features
focused on the Faraday API more quickly, without having to push it on all adapters immediately.
* With the community creating more and more adapters, we wanted to avoid having first and second-class adapters
by having some of them included with the gem and others available externally.
* Moving adapters into separate gems allow to solve the dependency issues once and for all.
Faraday will remain a dependency-free gem, while adapter gems will be able to automatically pull
any necessary dependency, without having to rely on the developer to do so.
#### So what will this mean for me?
We did our best to make this transition as painless as possible for you, so here is what we did.
* All adapters have already been moved out and released as separate gems.
They've then been re-added into Faraday's dependencies so that you wouldn't notice.
This means that immediately after v2.0 will be released, all the adapters that were previously available will be
already compatible with Faraday 2.0!
* We've setup an [Awesome Faraday](https://github.com/lostisland/awesome-faraday) repository, where you can find and discover adapters.
We also highlighted their unique features and level of compliance with Faraday's features.
### Others
* Rename `Faraday::Request#method` to `#http_method`.
## Faraday 1.0

View File

@ -27,17 +27,6 @@ require 'faraday/error'
require 'faraday/file_part'
require 'faraday/param_part'
unless defined?(JRUBY_VERSION)
require 'faraday/em_http'
require 'faraday/em_synchrony'
end
require 'faraday/excon'
require 'faraday/httpclient'
require 'faraday/net_http'
require 'faraday/net_http_persistent'
require 'faraday/patron'
require 'faraday/rack'
# This is the main namespace for Faraday.
#
# It provides methods to create {Connection} objects, and HTTP-related

View File

@ -1,49 +0,0 @@
# frozen_string_literal: true
unless defined?(JRUBY_VERSION)
RSpec.describe Faraday::Adapter::EMHttp do
features :request_body_on_query_methods, :reason_phrase_parse, :trace_method,
:skip_response_body_on_head, :parallel, :local_socket_binding
it_behaves_like 'an adapter'
it 'allows to provide adapter specific configs' do
url = URI('https://example.com:1234')
adapter = described_class.new nil, inactivity_timeout: 20
req = adapter.create_request(url: url, request: {})
expect(req.connopts.inactivity_timeout).to eq(20)
end
context 'Options' do
let(:request) { Faraday::RequestOptions.new }
let(:env) { { request: request } }
let(:options) { {} }
let(:adapter) { Faraday::Adapter::EMHttp.new }
it 'configures timeout' do
request.timeout = 5
adapter.configure_timeout(options, env)
expect(options[:inactivity_timeout]).to eq(5)
expect(options[:connect_timeout]).to eq(5)
end
it 'configures timeout and open_timeout' do
request.timeout = 5
request.open_timeout = 1
adapter.configure_timeout(options, env)
expect(options[:inactivity_timeout]).to eq(5)
expect(options[:connect_timeout]).to eq(1)
end
it 'configures all timeout settings' do
request.timeout = 5
request.read_timeout = 3
request.open_timeout = 1
adapter.configure_timeout(options, env)
expect(options[:inactivity_timeout]).to eq(3)
expect(options[:connect_timeout]).to eq(1)
end
end
end
end

View File

@ -1,18 +0,0 @@
# frozen_string_literal: true
unless defined?(JRUBY_VERSION)
RSpec.describe Faraday::Adapter::EMSynchrony do
features :request_body_on_query_methods, :reason_phrase_parse,
:skip_response_body_on_head, :parallel, :local_socket_binding
it_behaves_like 'an adapter'
it 'allows to provide adapter specific configs' do
url = URI('https://example.com:1234')
adapter = described_class.new nil, inactivity_timeout: 20
req = adapter.create_request(url: url, request: {})
expect(req.connopts.inactivity_timeout).to eq(20)
end
end
end

View File

@ -1,49 +0,0 @@
# frozen_string_literal: true
RSpec.describe Faraday::Adapter::Excon do
features :request_body_on_query_methods, :reason_phrase_parse, :trace_method
it_behaves_like 'an adapter'
it 'allows to provide adapter specific configs' do
url = URI('https://example.com:1234')
adapter = described_class.new(nil, debug_request: true)
conn = adapter.build_connection(url: url)
expect(conn.data[:debug_request]).to be_truthy
end
context 'config' do
let(:adapter) { Faraday::Adapter::Excon.new }
let(:request) { Faraday::RequestOptions.new }
let(:uri) { URI.parse('https://example.com') }
let(:env) { { request: request, url: uri } }
it 'sets timeout' do
request.timeout = 5
options = adapter.send(:opts_from_env, env)
expect(options[:read_timeout]).to eq(5)
expect(options[:write_timeout]).to eq(5)
expect(options[:connect_timeout]).to eq(5)
end
it 'sets timeout and open_timeout' do
request.timeout = 5
request.open_timeout = 3
options = adapter.send(:opts_from_env, env)
expect(options[:read_timeout]).to eq(5)
expect(options[:write_timeout]).to eq(5)
expect(options[:connect_timeout]).to eq(3)
end
it 'sets open_timeout' do
request.open_timeout = 3
options = adapter.send(:opts_from_env, env)
expect(options[:read_timeout]).to eq(nil)
expect(options[:write_timeout]).to eq(nil)
expect(options[:connect_timeout]).to eq(3)
end
end
end

View File

@ -1,73 +0,0 @@
# frozen_string_literal: true
RSpec.describe Faraday::Adapter::HTTPClient do
# ruby gem defaults for testing purposes
HTTPCLIENT_OPEN = 60
HTTPCLIENT_READ = 60
HTTPCLIENT_WRITE = 120
features :request_body_on_query_methods, :reason_phrase_parse, :compression,
:trace_method, :local_socket_binding
it_behaves_like 'an adapter'
it 'allows to provide adapter specific configs' do
adapter = described_class.new do |client|
client.keep_alive_timeout = 20
client.ssl_config.timeout = 25
end
client = adapter.build_connection(url: URI.parse('https://example.com'))
expect(client.keep_alive_timeout).to eq(20)
expect(client.ssl_config.timeout).to eq(25)
end
context 'Options' do
let(:request) { Faraday::RequestOptions.new }
let(:env) { { request: request } }
let(:options) { {} }
let(:adapter) { Faraday::Adapter::HTTPClient.new }
let(:client) { adapter.connection(url: URI.parse('https://example.com')) }
it 'configures timeout' do
assert_default_timeouts!
request.timeout = 5
adapter.configure_timeouts(client, request)
expect(client.connect_timeout).to eq(5)
expect(client.send_timeout).to eq(5)
expect(client.receive_timeout).to eq(5)
end
it 'configures open timeout' do
assert_default_timeouts!
request.open_timeout = 1
adapter.configure_timeouts(client, request)
expect(client.connect_timeout).to eq(1)
expect(client.send_timeout).to eq(HTTPCLIENT_WRITE)
expect(client.receive_timeout).to eq(HTTPCLIENT_READ)
end
it 'configures multiple timeouts' do
assert_default_timeouts!
request.open_timeout = 1
request.write_timeout = 10
request.read_timeout = 5
adapter.configure_timeouts(client, request)
expect(client.connect_timeout).to eq(1)
expect(client.send_timeout).to eq(10)
expect(client.receive_timeout).to eq(5)
end
def assert_default_timeouts!
expect(client.connect_timeout).to eq(HTTPCLIENT_OPEN)
expect(client.send_timeout).to eq(HTTPCLIENT_WRITE)
expect(client.receive_timeout).to eq(HTTPCLIENT_READ)
end
end
end

View File

@ -1,64 +1,11 @@
# frozen_string_literal: true
require 'faraday/net_http'
# Even though Faraday::Adapter::NetHttp is not shipped with Faraday anymore,
# this is still useful to test `it_behaves_like 'an adapter'` shared examples.
RSpec.describe Faraday::Adapter::NetHttp do
features :request_body_on_query_methods, :reason_phrase_parse, :compression, :streaming, :trace_method
it_behaves_like 'an adapter'
context 'checking http' do
let(:url) { URI('http://example.com') }
let(:adapter) { described_class.new }
let(:http) { adapter.send(:connection, url: url, request: {}) }
it { expect(http.port).to eq(80) }
it 'sets max_retries to 0' do
adapter.send(:configure_request, http, {})
expect(http.max_retries).to eq(0) if http.respond_to?(:max_retries=)
end
it 'supports write_timeout' do
adapter.send(:configure_request, http, write_timeout: 10)
expect(http.write_timeout).to eq(10) if http.respond_to?(:write_timeout=)
end
it 'supports open_timeout' do
adapter.send(:configure_request, http, open_timeout: 10)
expect(http.open_timeout).to eq(10)
end
it 'supports read_timeout' do
adapter.send(:configure_request, http, read_timeout: 10)
expect(http.read_timeout).to eq(10)
end
context 'with https url' do
let(:url) { URI('https://example.com') }
it { expect(http.port).to eq(443) }
end
context 'with http url including port' do
let(:url) { URI('https://example.com:1234') }
it { expect(http.port).to eq(1234) }
end
context 'with custom adapter config' do
let(:adapter) do
described_class.new do |http|
http.continue_timeout = 123
end
end
it do
adapter.send(:configure_request, http, {})
expect(http.continue_timeout).to eq(123)
end
end
end
end

View File

@ -1,18 +0,0 @@
# frozen_string_literal: true
RSpec.describe Faraday::Adapter::Patron, unless: defined?(JRUBY_VERSION) do
features :reason_phrase_parse
it_behaves_like 'an adapter'
it 'allows to provide adapter specific configs' do
conn = Faraday.new do |f|
f.adapter :patron do |session|
session.max_redirects = 10
raise 'Configuration block called'
end
end
expect { conn.get('/') }.to raise_error(RuntimeError, 'Configuration block called')
end
end

View File

@ -1,8 +0,0 @@
# frozen_string_literal: true
RSpec.describe Faraday::Adapter::Rack do
features :request_body_on_query_methods, :trace_method,
:skip_response_body_on_head
it_behaves_like 'an adapter', adapter_options: WebmockRackApp.new
end

View File

@ -1,7 +0,0 @@
# frozen_string_literal: true
RSpec.describe Faraday::Adapter::Typhoeus do
features :request_body_on_query_methods, :parallel, :trace_method
it_behaves_like 'an adapter'
end

View File

@ -1,68 +0,0 @@
# frozen_string_literal: true
# Rack app used to test the Rack adapter.
# Uses Webmock to check if requests are registered, in which case it returns
# the registered response.
class WebmockRackApp
def call(env)
req_signature = WebMock::RequestSignature.new(
req_method(env),
req_uri(env),
body: req_body(env),
headers: req_headers(env)
)
WebMock::RequestRegistry
.instance
.requested_signatures
.put(req_signature)
process_response(req_signature)
end
def req_method(env)
env['REQUEST_METHOD'].downcase.to_sym
end
def req_uri(env)
scheme = env['rack.url_scheme']
host = env['SERVER_NAME']
port = env['SERVER_PORT']
path = env['PATH_INFO']
query = env['QUERY_STRING']
url = +"#{scheme}://#{host}:#{port}#{path}"
url += "?#{query}" if query
uri = WebMock::Util::URI.heuristic_parse(url)
uri.path = uri.normalized_path.gsub('[^:]//', '/')
uri
end
def req_headers(env)
http_headers = env.select { |k, _| k.start_with?('HTTP_') }
.map { |k, v| [k[5..-1], v] }
.to_h
special_headers = Faraday::Adapter::Rack::SPECIAL_HEADERS
http_headers.merge(env.select { |k, _| special_headers.include?(k) })
end
def req_body(env)
env['rack.input'].read
end
def process_response(req_signature)
res = WebMock::StubRegistry.instance.response_for_request(req_signature)
if res.nil? && req_signature.uri.host == 'localhost'
raise Faraday::ConnectionFailed, 'Trying to connect to localhost'
end
raise WebMock::NetConnectNotAllowedError, req_signature unless res
raise Faraday::TimeoutError if res.should_timeout
[res.status[0], res.headers || {}, [res.body || '']]
end
end