avdi-faraday 0.8.1
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.
- data/Gemfile +27 -0
- data/LICENSE.md +20 -0
- data/README.md +250 -0
- data/Rakefile +87 -0
- data/config.ru +6 -0
- data/faraday.gemspec +86 -0
- data/lib/faraday.rb +276 -0
- data/lib/faraday/adapter.rb +71 -0
- data/lib/faraday/adapter/em_http.rb +217 -0
- data/lib/faraday/adapter/em_synchrony.rb +89 -0
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +66 -0
- data/lib/faraday/adapter/excon.rb +59 -0
- data/lib/faraday/adapter/httpclient.rb +92 -0
- data/lib/faraday/adapter/net_http.rb +116 -0
- data/lib/faraday/adapter/net_http_persistent.rb +37 -0
- data/lib/faraday/adapter/patron.rb +65 -0
- data/lib/faraday/adapter/rack.rb +57 -0
- data/lib/faraday/adapter/test.rb +162 -0
- data/lib/faraday/adapter/typhoeus.rb +107 -0
- data/lib/faraday/builder.rb +184 -0
- data/lib/faraday/connection.rb +468 -0
- data/lib/faraday/error.rb +40 -0
- data/lib/faraday/middleware.rb +41 -0
- data/lib/faraday/request.rb +101 -0
- data/lib/faraday/request/authorization.rb +40 -0
- data/lib/faraday/request/basic_authentication.rb +13 -0
- data/lib/faraday/request/multipart.rb +62 -0
- data/lib/faraday/request/retry.rb +67 -0
- data/lib/faraday/request/token_authentication.rb +15 -0
- data/lib/faraday/request/url_encoded.rb +35 -0
- data/lib/faraday/response.rb +99 -0
- data/lib/faraday/response/logger.rb +34 -0
- data/lib/faraday/response/raise_error.rb +16 -0
- data/lib/faraday/upload_io.rb +23 -0
- data/lib/faraday/utils.rb +274 -0
- data/script/test +91 -0
- data/test/adapters/default_test.rb +14 -0
- data/test/adapters/em_http_test.rb +19 -0
- data/test/adapters/em_synchrony_test.rb +20 -0
- data/test/adapters/excon_test.rb +15 -0
- data/test/adapters/httpclient_test.rb +16 -0
- data/test/adapters/integration.rb +193 -0
- data/test/adapters/logger_test.rb +37 -0
- data/test/adapters/net_http_persistent_test.rb +11 -0
- data/test/adapters/net_http_test.rb +49 -0
- data/test/adapters/patron_test.rb +17 -0
- data/test/adapters/rack_test.rb +26 -0
- data/test/adapters/test_middleware_test.rb +70 -0
- data/test/adapters/typhoeus_test.rb +20 -0
- data/test/authentication_middleware_test.rb +65 -0
- data/test/connection_test.rb +375 -0
- data/test/env_test.rb +183 -0
- data/test/helper.rb +75 -0
- data/test/live_server.rb +57 -0
- data/test/middleware/retry_test.rb +62 -0
- data/test/middleware_stack_test.rb +203 -0
- data/test/middleware_test.rb +12 -0
- data/test/request_middleware_test.rb +108 -0
- data/test/response_middleware_test.rb +74 -0
- metadata +182 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Adapter
|
3
|
+
class Patron < Faraday::Adapter
|
4
|
+
dependency 'patron'
|
5
|
+
|
6
|
+
def initialize(app, &block)
|
7
|
+
super(app)
|
8
|
+
@block = block if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
super
|
13
|
+
|
14
|
+
# TODO: support streaming requests
|
15
|
+
env[:body] = env[:body].read if env[:body].respond_to? :read
|
16
|
+
|
17
|
+
session = @session ||= create_session
|
18
|
+
|
19
|
+
if req = env[:request]
|
20
|
+
session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
|
21
|
+
session.connect_timeout = req[:open_timeout] if req[:open_timeout]
|
22
|
+
|
23
|
+
if proxy = req[:proxy]
|
24
|
+
session.proxy = proxy[:uri].to_s
|
25
|
+
if proxy[:user] && proxy[:password]
|
26
|
+
prepend_proxy_auth_string(proxy, session)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
response = begin
|
32
|
+
data = env[:body] ? env[:body].to_s : nil
|
33
|
+
session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data)
|
34
|
+
rescue Errno::ECONNREFUSED
|
35
|
+
raise Error::ConnectionFailed, $!
|
36
|
+
end
|
37
|
+
|
38
|
+
save_response(env, response.status, response.body, response.headers)
|
39
|
+
|
40
|
+
@app.call env
|
41
|
+
rescue ::Patron::TimeoutError => err
|
42
|
+
raise Faraday::Error::TimeoutError, err
|
43
|
+
end
|
44
|
+
|
45
|
+
if loaded? && defined?(::Patron::Request::VALID_ACTIONS)
|
46
|
+
# HAX: helps but doesn't work completely
|
47
|
+
# https://github.com/toland/patron/issues/34
|
48
|
+
::Patron::Request::VALID_ACTIONS.tap do |actions|
|
49
|
+
actions << :patch unless actions.include? :patch
|
50
|
+
actions << :options unless actions.include? :options
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_session
|
55
|
+
session = ::Patron::Session.new
|
56
|
+
@block.call(session) if @block
|
57
|
+
session
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def prepend_proxy_auth_string(proxy, session)
|
62
|
+
session.proxy.insert(7, "#{proxy[:user]}:#{proxy[:password]}@")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Adapter
|
3
|
+
# Sends requests to a Rack app.
|
4
|
+
#
|
5
|
+
# Examples
|
6
|
+
#
|
7
|
+
# class MyRackApp
|
8
|
+
# def call(env)
|
9
|
+
# [200, {'Content-Type' => 'text/html'}, ["hello world"]]
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# Faraday.new do |conn|
|
14
|
+
# conn.adapter :rack, MyRackApp
|
15
|
+
# end
|
16
|
+
class Rack < Faraday::Adapter
|
17
|
+
dependency 'rack/test'
|
18
|
+
|
19
|
+
# not prefixed with "HTTP_"
|
20
|
+
SPECIAL_HEADERS = %w[ CONTENT_LENGTH CONTENT_TYPE ]
|
21
|
+
|
22
|
+
def initialize(faraday_app, rack_app)
|
23
|
+
super(faraday_app)
|
24
|
+
mock_session = ::Rack::MockSession.new(rack_app)
|
25
|
+
@session = ::Rack::Test::Session.new(mock_session)
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(env)
|
29
|
+
super
|
30
|
+
rack_env = {
|
31
|
+
:method => env[:method],
|
32
|
+
:input => env[:body].respond_to?(:read) ? env[:body].read : env[:body]
|
33
|
+
}
|
34
|
+
|
35
|
+
env[:request_headers].each do |name, value|
|
36
|
+
name = name.upcase.tr('-', '_')
|
37
|
+
name = "HTTP_#{name}" unless SPECIAL_HEADERS.include? name
|
38
|
+
rack_env[name] = value
|
39
|
+
end if env[:request_headers]
|
40
|
+
|
41
|
+
timeout = env[:request][:timeout] || env[:request][:open_timeout]
|
42
|
+
response = if timeout
|
43
|
+
Timer.timeout(timeout, Faraday::Error::TimeoutError) { execute_request(env, rack_env) }
|
44
|
+
else
|
45
|
+
execute_request(env, rack_env)
|
46
|
+
end
|
47
|
+
|
48
|
+
save_response(env, response.status, response.body, response.headers)
|
49
|
+
@app.call env
|
50
|
+
end
|
51
|
+
|
52
|
+
def execute_request(env, rack_env)
|
53
|
+
@session.request(env[:url].to_s, rack_env)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Adapter
|
3
|
+
# test = Faraday::Connection.new do
|
4
|
+
# use Faraday::Adapter::Test do |stub|
|
5
|
+
# stub.get '/nigiri/sake.json' do
|
6
|
+
# [200, {}, 'hi world']
|
7
|
+
# end
|
8
|
+
# end
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# resp = test.get '/nigiri/sake.json'
|
12
|
+
# resp.body # => 'hi world'
|
13
|
+
#
|
14
|
+
class Test < Faraday::Adapter
|
15
|
+
attr_accessor :stubs
|
16
|
+
|
17
|
+
class Stubs
|
18
|
+
class NotFound < StandardError
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
# {:get => [Stub, Stub]}
|
23
|
+
@stack, @consumed = {}, {}
|
24
|
+
yield self if block_given?
|
25
|
+
end
|
26
|
+
|
27
|
+
def empty?
|
28
|
+
@stack.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
def match(request_method, path, body)
|
32
|
+
return false if !@stack.key?(request_method)
|
33
|
+
stack = @stack[request_method]
|
34
|
+
consumed = (@consumed[request_method] ||= [])
|
35
|
+
path = normalize_path(path)
|
36
|
+
|
37
|
+
if stub = matches?(stack, path, body)
|
38
|
+
consumed << stack.delete(stub)
|
39
|
+
stub
|
40
|
+
else
|
41
|
+
matches?(consumed, path, body)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def get(path, &block)
|
46
|
+
new_stub(:get, path, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def head(path, &block)
|
50
|
+
new_stub(:head, path, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def post(path, body=nil, &block)
|
54
|
+
new_stub(:post, path, body, &block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def put(path, body=nil, &block)
|
58
|
+
new_stub(:put, path, body, &block)
|
59
|
+
end
|
60
|
+
|
61
|
+
def patch(path, body=nil, &block)
|
62
|
+
new_stub(:patch, path, body, &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
def delete(path, &block)
|
66
|
+
new_stub(:delete, path, &block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def options(path, &block)
|
70
|
+
new_stub(:options, path, &block)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Raises an error if any of the stubbed calls have not been made.
|
74
|
+
def verify_stubbed_calls
|
75
|
+
failed_stubs = []
|
76
|
+
@stack.each do |method, stubs|
|
77
|
+
unless stubs.size == 0
|
78
|
+
failed_stubs.concat(stubs.map {|stub|
|
79
|
+
"Expected #{method} #{stub}."
|
80
|
+
})
|
81
|
+
end
|
82
|
+
end
|
83
|
+
raise failed_stubs.join(" ") unless failed_stubs.size == 0
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def new_stub(request_method, path, body=nil, &block)
|
89
|
+
(@stack[request_method] ||= []) << Stub.new(normalize_path(path), body, block)
|
90
|
+
end
|
91
|
+
|
92
|
+
def matches?(stack, path, body)
|
93
|
+
stack.detect { |stub| stub.matches?(path, body) }
|
94
|
+
end
|
95
|
+
|
96
|
+
# ensure leading + trailing slash
|
97
|
+
def normalize_path(path)
|
98
|
+
path = '/' + path if path.index('/') != 0
|
99
|
+
path = path.sub('?', '/?')
|
100
|
+
path = path + '/' unless $&
|
101
|
+
path.gsub('//', '/')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Stub < Struct.new(:path, :params, :body, :block)
|
106
|
+
def initialize(full, body, block)
|
107
|
+
path, query = full.split('?')
|
108
|
+
params = query ?
|
109
|
+
Faraday::Utils.parse_nested_query(query) :
|
110
|
+
{}
|
111
|
+
super path, params, body, block
|
112
|
+
end
|
113
|
+
|
114
|
+
def matches?(request_uri, request_body)
|
115
|
+
request_path, request_query = request_uri.split('?')
|
116
|
+
request_params = request_query ?
|
117
|
+
Faraday::Utils.parse_nested_query(request_query) :
|
118
|
+
{}
|
119
|
+
request_path == path &&
|
120
|
+
params_match?(request_params) &&
|
121
|
+
(body.to_s.size.zero? || request_body == body)
|
122
|
+
end
|
123
|
+
|
124
|
+
def params_match?(request_params)
|
125
|
+
params.keys.all? do |key|
|
126
|
+
request_params[key] == params[key]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def to_s
|
131
|
+
"#{path} #{body}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def initialize(app, stubs=nil, &block)
|
136
|
+
super(app)
|
137
|
+
@stubs = stubs || Stubs.new
|
138
|
+
configure(&block) if block
|
139
|
+
end
|
140
|
+
|
141
|
+
def configure
|
142
|
+
yield stubs
|
143
|
+
end
|
144
|
+
|
145
|
+
def call(env)
|
146
|
+
super
|
147
|
+
normalized_path = Faraday::Utils.normalize_path(env[:url])
|
148
|
+
|
149
|
+
if stub = stubs.match(env[:method], normalized_path, env[:body])
|
150
|
+
env[:params] = (query = env[:url].query) ?
|
151
|
+
Faraday::Utils.parse_nested_query(query) :
|
152
|
+
{}
|
153
|
+
status, headers, body = stub.block.call(env)
|
154
|
+
save_response(env, status, body, headers)
|
155
|
+
else
|
156
|
+
raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
|
157
|
+
end
|
158
|
+
@app.call(env)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Adapter
|
3
|
+
class Typhoeus < Faraday::Adapter
|
4
|
+
self.supports_parallel = true
|
5
|
+
|
6
|
+
def self.setup_parallel_manager(options = {})
|
7
|
+
options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
dependency 'typhoeus'
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
super
|
14
|
+
perform_request env
|
15
|
+
@app.call env
|
16
|
+
end
|
17
|
+
|
18
|
+
def perform_request(env)
|
19
|
+
read_body env
|
20
|
+
|
21
|
+
hydra = env[:parallel_manager] || self.class.setup_parallel_manager
|
22
|
+
hydra.queue request(env)
|
23
|
+
hydra.run unless parallel?(env)
|
24
|
+
rescue Errno::ECONNREFUSED
|
25
|
+
raise Error::ConnectionFailed, $!
|
26
|
+
end
|
27
|
+
|
28
|
+
# TODO: support streaming requests
|
29
|
+
def read_body(env)
|
30
|
+
env[:body] = env[:body].read if env[:body].respond_to? :read
|
31
|
+
end
|
32
|
+
|
33
|
+
def request(env)
|
34
|
+
req = ::Typhoeus::Request.new env[:url].to_s,
|
35
|
+
:method => env[:method],
|
36
|
+
:body => env[:body],
|
37
|
+
:headers => env[:request_headers],
|
38
|
+
:disable_ssl_peer_verification => (env[:ssl] && !env[:ssl].fetch(:verify, true))
|
39
|
+
|
40
|
+
configure_ssl req, env
|
41
|
+
configure_proxy req, env
|
42
|
+
configure_timeout req, env
|
43
|
+
configure_socket req, env
|
44
|
+
|
45
|
+
req.on_complete do |resp|
|
46
|
+
if resp.timed_out?
|
47
|
+
if parallel?(env)
|
48
|
+
# TODO: error callback in async mode
|
49
|
+
else
|
50
|
+
raise Faraday::Error::TimeoutError, "request timed out"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
save_response(env, resp.code, resp.body) do |response_headers|
|
55
|
+
response_headers.parse resp.headers
|
56
|
+
end
|
57
|
+
# in async mode, :response is initialized at this point
|
58
|
+
env[:response].finish(env) if parallel?(env)
|
59
|
+
end
|
60
|
+
|
61
|
+
req
|
62
|
+
end
|
63
|
+
|
64
|
+
def configure_ssl(req, env)
|
65
|
+
ssl = env[:ssl]
|
66
|
+
|
67
|
+
req.ssl_version = ssl[:version] if ssl[:version]
|
68
|
+
req.ssl_cert = ssl[:client_cert_file] if ssl[:client_cert_file]
|
69
|
+
req.ssl_key = ssl[:client_key_file] if ssl[:client_key_file]
|
70
|
+
req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file]
|
71
|
+
req.ssl_capath = ssl[:ca_path] if ssl[:ca_path]
|
72
|
+
end
|
73
|
+
|
74
|
+
def configure_proxy(req, env)
|
75
|
+
proxy = request_options(env)[:proxy]
|
76
|
+
return unless proxy
|
77
|
+
|
78
|
+
req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}"
|
79
|
+
|
80
|
+
if proxy[:username] && proxy[:password]
|
81
|
+
req.proxy_username = proxy[:username]
|
82
|
+
req.proxy_password = proxy[:password]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def configure_timeout(req, env)
|
87
|
+
env_req = request_options(env)
|
88
|
+
req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
|
89
|
+
req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
|
90
|
+
end
|
91
|
+
|
92
|
+
def configure_socket(req, env)
|
93
|
+
if bind = request_options(env)[:bind]
|
94
|
+
req.interface = bind[:host]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def request_options(env)
|
99
|
+
env[:request]
|
100
|
+
end
|
101
|
+
|
102
|
+
def parallel?(env)
|
103
|
+
!!env[:parallel_manager]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
module Faraday
|
2
|
+
# Possibly going to extend this a bit.
|
3
|
+
#
|
4
|
+
# Faraday::Connection.new(:url => 'http://sushi.com') do |builder|
|
5
|
+
# builder.request :url_encoded # Faraday::Request::UrlEncoded
|
6
|
+
# builder.adapter :net_http # Faraday::Adapter::NetHttp
|
7
|
+
# end
|
8
|
+
class Builder
|
9
|
+
attr_accessor :handlers
|
10
|
+
|
11
|
+
# Error raised when trying to modify the stack after calling `lock!`
|
12
|
+
class StackLocked < RuntimeError; end
|
13
|
+
|
14
|
+
# borrowed from ActiveSupport::Dependencies::Reference &
|
15
|
+
# ActionDispatch::MiddlewareStack::Middleware
|
16
|
+
class Handler
|
17
|
+
@@constants = Hash.new { |h, k|
|
18
|
+
h[k] = k.respond_to?(:constantize) ? k.constantize : Object.const_get(k)
|
19
|
+
}
|
20
|
+
|
21
|
+
attr_reader :name, :args
|
22
|
+
|
23
|
+
def initialize(klass, *args, &block)
|
24
|
+
@name = klass.to_s
|
25
|
+
@@constants[@name] = klass if klass.respond_to?(:name)
|
26
|
+
@args, @block = args, block
|
27
|
+
end
|
28
|
+
|
29
|
+
def klass() @@constants[@name] end
|
30
|
+
def inspect() @name end
|
31
|
+
|
32
|
+
def ==(other)
|
33
|
+
if other.is_a? Handler
|
34
|
+
self.name == other.name
|
35
|
+
elsif other.respond_to? :name
|
36
|
+
klass == other
|
37
|
+
else
|
38
|
+
@name == other.to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def build(app)
|
43
|
+
klass.new(app, *@args, &@block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def adapter?
|
47
|
+
klass.respond_to?(:adapter?) && klass.adapter?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(handlers = [])
|
52
|
+
@handlers = handlers
|
53
|
+
if block_given?
|
54
|
+
build(&Proc.new)
|
55
|
+
elsif @handlers.empty?
|
56
|
+
# default stack, if nothing else is configured
|
57
|
+
self.request :url_encoded
|
58
|
+
self.adapter Faraday.default_adapter
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def build(options = {})
|
63
|
+
raise_if_locked
|
64
|
+
clear unless options[:keep]
|
65
|
+
yield self if block_given?
|
66
|
+
end
|
67
|
+
|
68
|
+
def clear
|
69
|
+
@handlers.clear
|
70
|
+
end
|
71
|
+
|
72
|
+
def [](idx)
|
73
|
+
@handlers[idx]
|
74
|
+
end
|
75
|
+
|
76
|
+
def ==(other)
|
77
|
+
other.is_a?(self.class) && @handlers == other.handlers
|
78
|
+
end
|
79
|
+
|
80
|
+
def dup
|
81
|
+
self.class.new(@handlers.dup)
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_app(inner_app)
|
85
|
+
# last added handler is the deepest and thus closest to the inner app
|
86
|
+
@handlers.reverse.inject(inner_app) { |app, handler| handler.build(app) }
|
87
|
+
end
|
88
|
+
|
89
|
+
# Locks the middleware stack to ensure no further modifications are possible.
|
90
|
+
def lock!
|
91
|
+
@handlers.freeze
|
92
|
+
end
|
93
|
+
|
94
|
+
def locked?
|
95
|
+
@handlers.frozen?
|
96
|
+
end
|
97
|
+
|
98
|
+
def use(klass, *args, &block)
|
99
|
+
if klass.is_a? Symbol
|
100
|
+
use_symbol(Faraday::Middleware, klass, *args, &block)
|
101
|
+
else
|
102
|
+
raise_if_locked
|
103
|
+
@handlers << self.class::Handler.new(klass, *args, &block)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def request(key, *args, &block)
|
108
|
+
use_symbol(Faraday::Request, key, *args, &block)
|
109
|
+
end
|
110
|
+
|
111
|
+
def response(key, *args, &block)
|
112
|
+
use_symbol(Faraday::Response, key, *args, &block)
|
113
|
+
end
|
114
|
+
|
115
|
+
def adapter(key=nil, *args, &block)
|
116
|
+
if [key, *args, block].none?
|
117
|
+
find_adapter
|
118
|
+
else
|
119
|
+
use_symbol(Faraday::Adapter, key, *args, &block)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def has_adapter?
|
124
|
+
!!find_adapter
|
125
|
+
end
|
126
|
+
|
127
|
+
## methods to push onto the various positions in the stack:
|
128
|
+
|
129
|
+
def insert(index, *args, &block)
|
130
|
+
raise_if_locked
|
131
|
+
index = assert_index(index)
|
132
|
+
handler = self.class::Handler.new(*args, &block)
|
133
|
+
@handlers.insert(index, handler)
|
134
|
+
end
|
135
|
+
|
136
|
+
alias_method :insert_before, :insert
|
137
|
+
|
138
|
+
def insert_after(index, *args, &block)
|
139
|
+
index = assert_index(index)
|
140
|
+
insert(index + 1, *args, &block)
|
141
|
+
end
|
142
|
+
|
143
|
+
def swap(index, *args, &block)
|
144
|
+
raise_if_locked
|
145
|
+
index = assert_index(index)
|
146
|
+
@handlers.delete_at(index)
|
147
|
+
insert(index, *args, &block)
|
148
|
+
end
|
149
|
+
|
150
|
+
def delete(handler)
|
151
|
+
raise_if_locked
|
152
|
+
@handlers.delete(handler)
|
153
|
+
end
|
154
|
+
|
155
|
+
def adapter=(adapter_args)
|
156
|
+
clear_adapters
|
157
|
+
adapter(*adapter_args)
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def raise_if_locked
|
163
|
+
raise StackLocked, "can't modify middleware stack after making a request" if locked?
|
164
|
+
end
|
165
|
+
|
166
|
+
def use_symbol(mod, key, *args, &block)
|
167
|
+
use(mod.lookup_middleware(key), *args, &block)
|
168
|
+
end
|
169
|
+
|
170
|
+
def assert_index(index)
|
171
|
+
idx = index.is_a?(Integer) ? index : @handlers.index(index)
|
172
|
+
raise "No such handler: #{index.inspect}" unless idx
|
173
|
+
idx
|
174
|
+
end
|
175
|
+
|
176
|
+
def find_adapter
|
177
|
+
@handlers.detect{|h| h.adapter?}
|
178
|
+
end
|
179
|
+
|
180
|
+
def clear_adapters
|
181
|
+
@handlers.delete_if{|h| h.adapter?}
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|