faraday 0.7.6 → 0.8.0.rc2
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 +1 -4
- data/README.md +148 -131
- data/Rakefile +12 -60
- data/faraday.gemspec +11 -32
- data/lib/faraday.rb +59 -12
- data/lib/faraday/adapter.rb +17 -1
- data/lib/faraday/adapter/em_http.rb +204 -0
- data/lib/faraday/adapter/em_synchrony.rb +66 -16
- data/lib/faraday/adapter/em_synchrony/parallel_manager.rb +66 -0
- data/lib/faraday/adapter/net_http.rb +1 -1
- data/lib/faraday/adapter/test.rb +13 -6
- data/lib/faraday/adapter/typhoeus.rb +64 -29
- data/lib/faraday/builder.rb +12 -17
- data/lib/faraday/connection.rb +131 -102
- data/lib/faraday/middleware.rb +17 -9
- data/lib/faraday/request.rb +40 -25
- data/lib/faraday/request/basic_authentication.rb +17 -0
- data/lib/faraday/request/retry.rb +21 -0
- data/lib/faraday/request/token_authentication.rb +21 -0
- data/lib/faraday/response.rb +2 -1
- data/lib/faraday/utils.rb +122 -18
- data/test/adapters/live_test.rb +35 -30
- data/test/adapters/logger_test.rb +2 -2
- data/test/adapters/typhoeus_test.rb +1 -1
- data/test/authentication_middleware_test.rb +48 -0
- data/test/connection_test.rb +171 -83
- data/test/env_test.rb +28 -3
- data/test/helper.rb +1 -1
- data/test/middleware/retry_test.rb +25 -0
- data/test/middleware_stack_test.rb +56 -2
- data/test/request_middleware_test.rb +2 -47
- data/test/response_middleware_test.rb +4 -4
- metadata +25 -39
- data/lib/faraday/request/json.rb +0 -35
@@ -1,11 +1,21 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
1
3
|
module Faraday
|
2
4
|
class Adapter
|
3
5
|
class EMSynchrony < Faraday::Adapter
|
6
|
+
|
4
7
|
dependency do
|
5
8
|
require 'em-synchrony/em-http'
|
9
|
+
require 'em-synchrony/em-multi'
|
6
10
|
require 'fiber'
|
7
11
|
end
|
8
12
|
|
13
|
+
self.supports_parallel = true
|
14
|
+
|
15
|
+
def self.setup_parallel_manager(options = {})
|
16
|
+
ParallelManager.new
|
17
|
+
end
|
18
|
+
|
9
19
|
def call(env)
|
10
20
|
super
|
11
21
|
request = EventMachine::HttpRequest.new(URI::parse(env[:url].to_s))
|
@@ -22,10 +32,10 @@ module Faraday
|
|
22
32
|
|
23
33
|
if req = env[:request]
|
24
34
|
if proxy = req[:proxy]
|
25
|
-
uri =
|
35
|
+
uri = URI.parse(proxy[:uri])
|
26
36
|
options[:proxy] = {
|
27
37
|
:host => uri.host,
|
28
|
-
:port => uri.
|
38
|
+
:port => uri.port
|
29
39
|
}
|
30
40
|
if proxy[:username] && proxy[:password]
|
31
41
|
options[:proxy][:authorization] = [proxy[:username], proxy[:password]]
|
@@ -38,22 +48,41 @@ module Faraday
|
|
38
48
|
end
|
39
49
|
end
|
40
50
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
http_method = env[:method].to_s.downcase.to_sym
|
52
|
+
|
53
|
+
# Queue requests for parallel execution.
|
54
|
+
if env[:parallel_manager]
|
55
|
+
env[:parallel_manager].add(request, http_method, options) do |resp|
|
56
|
+
save_response(env, resp.response_header.status, resp.response) do |resp_headers|
|
57
|
+
resp.response_header.each do |name, value|
|
58
|
+
resp_headers[name.to_sym] = value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Finalize the response object with values from `env`.
|
63
|
+
env[:response].finish(env)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Execute single request.
|
50
67
|
else
|
51
|
-
client =
|
52
|
-
|
68
|
+
client = nil
|
69
|
+
block = lambda { request.send(http_method, options) }
|
53
70
|
|
54
|
-
|
55
|
-
|
56
|
-
|
71
|
+
if !EM.reactor_running?
|
72
|
+
EM.run do
|
73
|
+
Fiber.new {
|
74
|
+
client = block.call
|
75
|
+
EM.stop
|
76
|
+
}.resume
|
77
|
+
end
|
78
|
+
else
|
79
|
+
client = block.call
|
80
|
+
end
|
81
|
+
|
82
|
+
save_response(env, client.response_header.status, client.response) do |resp_headers|
|
83
|
+
client.response_header.each do |name, value|
|
84
|
+
resp_headers[name.to_sym] = value
|
85
|
+
end
|
57
86
|
end
|
58
87
|
end
|
59
88
|
|
@@ -64,3 +93,24 @@ module Faraday
|
|
64
93
|
end
|
65
94
|
end
|
66
95
|
end
|
96
|
+
|
97
|
+
require 'faraday/adapter/em_synchrony/parallel_manager'
|
98
|
+
|
99
|
+
# add missing patch(), options() methods
|
100
|
+
EventMachine::HTTPMethods.module_eval do
|
101
|
+
([:patch, :options] - instance_methods).each do |type|
|
102
|
+
module_eval %[
|
103
|
+
def #{type}(options = {}, &blk)
|
104
|
+
f = Fiber.current
|
105
|
+
conn = setup_request(:#{type}, options, &blk)
|
106
|
+
if conn.error.nil?
|
107
|
+
conn.callback { f.resume(conn) }
|
108
|
+
conn.errback { f.resume(conn) }
|
109
|
+
Fiber.yield
|
110
|
+
else
|
111
|
+
conn
|
112
|
+
end
|
113
|
+
end
|
114
|
+
]
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Adapter
|
3
|
+
class EMSynchrony < Faraday::Adapter
|
4
|
+
class ParallelManager
|
5
|
+
|
6
|
+
# Add requests to queue. The `request` argument should be a
|
7
|
+
# `EM::HttpRequest` object.
|
8
|
+
def add(request, method, *args, &block)
|
9
|
+
queue << {
|
10
|
+
:request => request,
|
11
|
+
:method => method,
|
12
|
+
:args => args,
|
13
|
+
:block => block
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
# Run all requests on queue with `EM::Synchrony::Multi`, wrapping
|
18
|
+
# it in a reactor and fiber if needed.
|
19
|
+
def run
|
20
|
+
result = nil
|
21
|
+
if !EM.reactor_running?
|
22
|
+
EM.run {
|
23
|
+
Fiber.new do
|
24
|
+
result = perform
|
25
|
+
EM.stop
|
26
|
+
end.resume
|
27
|
+
}
|
28
|
+
else
|
29
|
+
result = perform
|
30
|
+
end
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# The request queue.
|
38
|
+
def queue
|
39
|
+
@queue ||= []
|
40
|
+
end
|
41
|
+
|
42
|
+
# Main `EM::Synchrony::Multi` performer.
|
43
|
+
def perform
|
44
|
+
multi = ::EM::Synchrony::Multi.new
|
45
|
+
|
46
|
+
queue.each do |item|
|
47
|
+
method = "a#{item[:method]}".to_sym
|
48
|
+
|
49
|
+
req = item[:request].send(method, *item[:args])
|
50
|
+
req.callback(&item[:block])
|
51
|
+
|
52
|
+
req_name = "req_#{multi.requests.size}".to_sym
|
53
|
+
multi.add(req_name, req)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Clear the queue, so parallel manager objects can be reused.
|
57
|
+
@queue = []
|
58
|
+
|
59
|
+
# Block fiber until all requests have returned.
|
60
|
+
multi.perform
|
61
|
+
end
|
62
|
+
|
63
|
+
end # ParallelManager
|
64
|
+
end # EMSynchrony
|
65
|
+
end # Adapter
|
66
|
+
end # Faraday
|
@@ -13,7 +13,7 @@ module Faraday
|
|
13
13
|
url = env[:url]
|
14
14
|
req = env[:request]
|
15
15
|
|
16
|
-
http = net_http_class(env).new(url.host, url.
|
16
|
+
http = net_http_class(env).new(url.host, url.port)
|
17
17
|
|
18
18
|
if http.use_ssl = (url.scheme == 'https' && (ssl = env[:ssl]) && true)
|
19
19
|
http.verify_mode = ssl[:verify_mode] || begin
|
data/lib/faraday/adapter/test.rb
CHANGED
@@ -14,8 +14,6 @@ module Faraday
|
|
14
14
|
class Test < Faraday::Adapter
|
15
15
|
attr_accessor :stubs
|
16
16
|
|
17
|
-
def self.loaded?() false end
|
18
|
-
|
19
17
|
class Stubs
|
20
18
|
class NotFound < StandardError
|
21
19
|
end
|
@@ -34,6 +32,7 @@ module Faraday
|
|
34
32
|
return false if !@stack.key?(request_method)
|
35
33
|
stack = @stack[request_method]
|
36
34
|
consumed = (@consumed[request_method] ||= [])
|
35
|
+
path = normalize_path(path)
|
37
36
|
|
38
37
|
if stub = matches?(stack, path, body)
|
39
38
|
consumed << stack.delete(stub)
|
@@ -87,19 +86,27 @@ module Faraday
|
|
87
86
|
protected
|
88
87
|
|
89
88
|
def new_stub(request_method, path, body=nil, &block)
|
90
|
-
(@stack[request_method] ||= []) << Stub.new(path, body, block)
|
89
|
+
(@stack[request_method] ||= []) << Stub.new(normalize_path(path), body, block)
|
91
90
|
end
|
92
91
|
|
93
92
|
def matches?(stack, path, body)
|
94
93
|
stack.detect { |stub| stub.matches?(path, body) }
|
95
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
|
96
103
|
end
|
97
104
|
|
98
105
|
class Stub < Struct.new(:path, :params, :body, :block)
|
99
106
|
def initialize(full, body, block)
|
100
107
|
path, query = full.split('?')
|
101
108
|
params = query ?
|
102
|
-
|
109
|
+
Faraday::Utils.parse_nested_query(query) :
|
103
110
|
{}
|
104
111
|
super path, params, body, block
|
105
112
|
end
|
@@ -107,7 +114,7 @@ module Faraday
|
|
107
114
|
def matches?(request_uri, request_body)
|
108
115
|
request_path, request_query = request_uri.split('?')
|
109
116
|
request_params = request_query ?
|
110
|
-
|
117
|
+
Faraday::Utils.parse_nested_query(request_query) :
|
111
118
|
{}
|
112
119
|
request_path == path &&
|
113
120
|
params_match?(request_params) &&
|
@@ -141,7 +148,7 @@ module Faraday
|
|
141
148
|
|
142
149
|
if stub = stubs.match(env[:method], normalized_path, env[:body])
|
143
150
|
env[:params] = (query = env[:url].query) ?
|
144
|
-
|
151
|
+
Faraday::Utils.parse_nested_query(query) :
|
145
152
|
{}
|
146
153
|
status, headers, body = stub.block.call(env)
|
147
154
|
save_response(env, status, body, headers)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Faraday
|
2
2
|
class Adapter
|
3
3
|
class Typhoeus < Faraday::Adapter
|
4
|
-
self.
|
4
|
+
self.supports_parallel = true
|
5
5
|
|
6
6
|
def self.setup_parallel_manager(options = {})
|
7
7
|
options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options)
|
@@ -11,53 +11,88 @@ module Faraday
|
|
11
11
|
|
12
12
|
def call(env)
|
13
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
|
14
27
|
|
15
|
-
|
28
|
+
# TODO: support streaming requests
|
29
|
+
def read_body(env)
|
16
30
|
env[:body] = env[:body].read if env[:body].respond_to? :read
|
31
|
+
end
|
17
32
|
|
33
|
+
def request(env)
|
18
34
|
req = ::Typhoeus::Request.new env[:url].to_s,
|
19
35
|
:method => env[:method],
|
20
36
|
:body => env[:body],
|
21
37
|
:headers => env[:request_headers],
|
22
38
|
:disable_ssl_peer_verification => (env[:ssl] && !env[:ssl].fetch(:verify, true))
|
23
39
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file]
|
28
|
-
req.ssl_capath = ssl[:ca_path] if ssl[:ca_path]
|
29
|
-
end
|
40
|
+
configure_ssl req, env
|
41
|
+
configure_proxy req, env
|
42
|
+
configure_timeout req, env
|
30
43
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
req.proxy_password = proxy[:password]
|
44
|
+
req.on_complete do |resp|
|
45
|
+
if resp.timed_out?
|
46
|
+
if parallel?(env)
|
47
|
+
# TODO: error callback in async mode
|
48
|
+
else
|
49
|
+
raise Faraday::Error::TimeoutError, "request timed out"
|
50
|
+
end
|
39
51
|
end
|
40
|
-
end
|
41
52
|
|
42
|
-
req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
|
43
|
-
req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
|
44
|
-
|
45
|
-
is_parallel = !!env[:parallel_manager]
|
46
|
-
req.on_complete do |resp|
|
47
53
|
save_response(env, resp.code, resp.body) do |response_headers|
|
48
54
|
response_headers.parse resp.headers
|
49
55
|
end
|
50
56
|
# in async mode, :response is initialized at this point
|
51
|
-
env[:response].finish(env) if
|
57
|
+
env[:response].finish(env) if parallel?(env)
|
52
58
|
end
|
53
59
|
|
54
|
-
|
55
|
-
|
56
|
-
hydra.run unless is_parallel
|
60
|
+
req
|
61
|
+
end
|
57
62
|
|
58
|
-
|
59
|
-
|
60
|
-
|
63
|
+
def configure_ssl(req, env)
|
64
|
+
ssl = env[:ssl]
|
65
|
+
|
66
|
+
req.ssl_cert = ssl[:client_cert_file] if ssl[:client_cert_file]
|
67
|
+
req.ssl_key = ssl[:client_key_file] if ssl[:client_key_file]
|
68
|
+
req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file]
|
69
|
+
req.ssl_capath = ssl[:ca_path] if ssl[:ca_path]
|
70
|
+
end
|
71
|
+
|
72
|
+
def configure_proxy(req, env)
|
73
|
+
proxy = request_options(env)[:proxy]
|
74
|
+
return unless proxy
|
75
|
+
|
76
|
+
req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}"
|
77
|
+
|
78
|
+
if proxy[:username] && proxy[:password]
|
79
|
+
req.proxy_username = proxy[:username]
|
80
|
+
req.proxy_password = proxy[:password]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def configure_timeout(req, env)
|
85
|
+
env_req = request_options(env)
|
86
|
+
req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
|
87
|
+
req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
|
88
|
+
end
|
89
|
+
|
90
|
+
def request_options(env)
|
91
|
+
env[:request]
|
92
|
+
end
|
93
|
+
|
94
|
+
def parallel?(env)
|
95
|
+
!!env[:parallel_manager]
|
61
96
|
end
|
62
97
|
end
|
63
98
|
end
|
data/lib/faraday/builder.rb
CHANGED
@@ -8,10 +8,6 @@ module Faraday
|
|
8
8
|
class Builder
|
9
9
|
attr_accessor :handlers
|
10
10
|
|
11
|
-
def self.create
|
12
|
-
new { |builder| yield builder }
|
13
|
-
end
|
14
|
-
|
15
11
|
# Error raised when trying to modify the stack after calling `lock!`
|
16
12
|
class StackLocked < RuntimeError; end
|
17
13
|
|
@@ -91,24 +87,24 @@ module Faraday
|
|
91
87
|
@handlers.frozen?
|
92
88
|
end
|
93
89
|
|
94
|
-
def use(klass, *args)
|
95
|
-
|
96
|
-
|
97
|
-
|
90
|
+
def use(klass, *args, &block)
|
91
|
+
if klass.is_a? Symbol
|
92
|
+
use_symbol(Faraday::Middleware, klass, *args, &block)
|
93
|
+
else
|
94
|
+
raise_if_locked
|
95
|
+
@handlers << self.class::Handler.new(klass, *args, &block)
|
96
|
+
end
|
98
97
|
end
|
99
98
|
|
100
|
-
def request(key, *args)
|
101
|
-
block = block_given? ? Proc.new : nil
|
99
|
+
def request(key, *args, &block)
|
102
100
|
use_symbol(Faraday::Request, key, *args, &block)
|
103
101
|
end
|
104
102
|
|
105
|
-
def response(key, *args)
|
106
|
-
block = block_given? ? Proc.new : nil
|
103
|
+
def response(key, *args, &block)
|
107
104
|
use_symbol(Faraday::Response, key, *args, &block)
|
108
105
|
end
|
109
106
|
|
110
|
-
def adapter(key, *args)
|
111
|
-
block = block_given? ? Proc.new : nil
|
107
|
+
def adapter(key, *args, &block)
|
112
108
|
use_symbol(Faraday::Adapter, key, *args, &block)
|
113
109
|
end
|
114
110
|
|
@@ -146,9 +142,8 @@ module Faraday
|
|
146
142
|
raise StackLocked, "can't modify middleware stack after making a request" if locked?
|
147
143
|
end
|
148
144
|
|
149
|
-
def use_symbol(mod, key, *args)
|
150
|
-
|
151
|
-
use(mod.lookup_module(key), *args, &block)
|
145
|
+
def use_symbol(mod, key, *args, &block)
|
146
|
+
use(mod.lookup_middleware(key), *args, &block)
|
152
147
|
end
|
153
148
|
|
154
149
|
def assert_index(index)
|
data/lib/faraday/connection.rb
CHANGED
@@ -1,21 +1,18 @@
|
|
1
|
-
require 'addressable/uri'
|
2
1
|
require 'base64'
|
3
2
|
require 'cgi'
|
4
3
|
require 'set'
|
5
|
-
require '
|
6
|
-
require '
|
7
|
-
|
8
|
-
|
4
|
+
require 'forwardable'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
Faraday.require_libs 'builder', 'request', 'response', 'utils'
|
9
8
|
|
10
9
|
module Faraday
|
11
10
|
class Connection
|
12
|
-
include Addressable
|
13
|
-
|
14
11
|
METHODS = Set.new [:get, :post, :put, :delete, :head, :patch, :options]
|
15
12
|
METHODS_WITH_BODIES = Set.new [:post, :put, :patch, :options]
|
16
13
|
|
17
|
-
|
18
|
-
|
14
|
+
attr_reader :params, :headers, :url_prefix, :builder, :options, :ssl, :parallel_manager
|
15
|
+
attr_writer :default_parallel_manager
|
19
16
|
|
20
17
|
# :url
|
21
18
|
# :params
|
@@ -27,47 +24,43 @@ module Faraday
|
|
27
24
|
options = url
|
28
25
|
url = options[:url]
|
29
26
|
end
|
30
|
-
@headers
|
31
|
-
@params
|
32
|
-
@options
|
33
|
-
@ssl
|
34
|
-
|
27
|
+
@headers = Utils::Headers.new
|
28
|
+
@params = Utils::ParamsHash.new
|
29
|
+
@options = options[:request] || {}
|
30
|
+
@ssl = options[:ssl] || {}
|
31
|
+
|
32
|
+
@parallel_manager = nil
|
33
|
+
@default_parallel_manager = options[:parallel_manager]
|
35
34
|
|
36
|
-
@
|
37
|
-
|
35
|
+
@builder = options[:builder] || begin
|
36
|
+
# pass an empty block to Builder so it doesn't assume default middleware
|
37
|
+
block = block_given?? Proc.new {|b| } : nil
|
38
|
+
Builder.new(&block)
|
39
|
+
end
|
38
40
|
|
39
|
-
|
40
|
-
proxy(options[:proxy])
|
41
|
+
self.url_prefix = url || 'http:/'
|
41
42
|
|
42
43
|
@params.update options[:params] if options[:params]
|
43
44
|
@headers.update options[:headers] if options[:headers]
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
else
|
48
|
-
@builder = options[:builder] || Builder.new
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def use(klass, *args, &block)
|
53
|
-
@builder.use(klass, *args, &block)
|
54
|
-
end
|
46
|
+
@proxy = nil
|
47
|
+
proxy(options.fetch(:proxy) { ENV['http_proxy'] })
|
55
48
|
|
56
|
-
|
57
|
-
@builder.request(key, *args, &block)
|
49
|
+
yield self if block_given?
|
58
50
|
end
|
59
51
|
|
60
|
-
|
61
|
-
|
52
|
+
# Public: Replace default query parameters.
|
53
|
+
def params=(hash)
|
54
|
+
@params.replace hash
|
62
55
|
end
|
63
56
|
|
64
|
-
|
65
|
-
|
57
|
+
# Public: Replace default request headers.
|
58
|
+
def headers=(hash)
|
59
|
+
@headers.replace hash
|
66
60
|
end
|
67
61
|
|
68
|
-
|
69
|
-
|
70
|
-
end
|
62
|
+
extend Forwardable
|
63
|
+
def_delegators :builder, :build, :use, :request, :response, :adapter
|
71
64
|
|
72
65
|
# The "rack app" wrapped in middleware. All requests are sent here.
|
73
66
|
#
|
@@ -88,58 +81,62 @@ module Faraday
|
|
88
81
|
end
|
89
82
|
end
|
90
83
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
def put(url = nil, body = nil, headers = nil)
|
102
|
-
block = block_given? ? Proc.new : nil
|
103
|
-
run_request(:put, url, body, headers, &block)
|
104
|
-
end
|
105
|
-
|
106
|
-
def patch(url = nil, body = nil, headers = nil)
|
107
|
-
block = block_given? ? Proc.new : nil
|
108
|
-
run_request(:patch, url, body, headers, &block)
|
109
|
-
end
|
110
|
-
|
111
|
-
def head(url = nil, headers = nil)
|
112
|
-
block = block_given? ? Proc.new : nil
|
113
|
-
run_request(:head, url, nil, headers, &block)
|
84
|
+
# get/head/delete(url, params, headers)
|
85
|
+
%w[get head delete].each do |method|
|
86
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
87
|
+
def #{method}(url = nil, params = nil, headers = nil)
|
88
|
+
run_request(:#{method}, url, nil, headers) { |request|
|
89
|
+
request.params.update(params) if params
|
90
|
+
yield request if block_given?
|
91
|
+
}
|
92
|
+
end
|
93
|
+
RUBY
|
114
94
|
end
|
115
95
|
|
116
|
-
|
117
|
-
|
118
|
-
|
96
|
+
# post/put/patch(url, body, headers)
|
97
|
+
%w[post put patch].each do |method|
|
98
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
99
|
+
def #{method}(url = nil, body = nil, headers = nil, &block)
|
100
|
+
run_request(:#{method}, url, body, headers, &block)
|
101
|
+
end
|
102
|
+
RUBY
|
119
103
|
end
|
120
104
|
|
121
105
|
def basic_auth(login, pass)
|
122
|
-
|
123
|
-
auth.gsub!("\n", "")
|
124
|
-
@headers['authorization'] = "Basic #{auth}"
|
106
|
+
@builder.insert(0, Faraday::Request::BasicAuthentication, login, pass)
|
125
107
|
end
|
126
108
|
|
127
109
|
def token_auth(token, options = {})
|
128
|
-
|
129
|
-
|
130
|
-
|
110
|
+
@builder.insert(0, Faraday::Request::TokenAuthentication, token, options)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Internal: Traverse the middleware stack in search of a
|
114
|
+
# parallel-capable adapter.
|
115
|
+
#
|
116
|
+
# Yields in case of not found.
|
117
|
+
#
|
118
|
+
# Returns a parallel manager or nil if not found.
|
119
|
+
def default_parallel_manager
|
120
|
+
@default_parallel_manager ||= begin
|
121
|
+
handler = @builder.handlers.find { |h|
|
122
|
+
h.klass.respond_to?(:supports_parallel?) and h.klass.supports_parallel?
|
123
|
+
}
|
124
|
+
if handler then handler.klass.setup_parallel_manager
|
125
|
+
elsif block_given? then yield
|
126
|
+
end
|
131
127
|
end
|
132
|
-
# 21 = "Authorization: Token ".size
|
133
|
-
comma = ",\n#{' ' * 21}"
|
134
|
-
@headers['authorization'] = "Token #{values * comma}"
|
135
128
|
end
|
136
129
|
|
137
130
|
def in_parallel?
|
138
131
|
!!@parallel_manager
|
139
132
|
end
|
140
133
|
|
141
|
-
def in_parallel(manager)
|
142
|
-
@parallel_manager = manager
|
134
|
+
def in_parallel(manager = nil)
|
135
|
+
@parallel_manager = manager || default_parallel_manager {
|
136
|
+
warn "Warning: `in_parallel` called but no parallel-capable adapter on Faraday stack"
|
137
|
+
warn caller[2,10].join("\n")
|
138
|
+
nil
|
139
|
+
}
|
143
140
|
yield
|
144
141
|
@parallel_manager && @parallel_manager.run
|
145
142
|
ensure
|
@@ -151,15 +148,23 @@ module Faraday
|
|
151
148
|
|
152
149
|
@proxy = if arg.is_a? Hash
|
153
150
|
uri = arg.fetch(:uri) { raise ArgumentError, "no :uri option" }
|
154
|
-
arg.merge :uri => URI
|
151
|
+
arg.merge :uri => self.class.URI(uri)
|
155
152
|
else
|
156
|
-
{:uri => URI
|
153
|
+
{:uri => self.class.URI(arg)}
|
157
154
|
end
|
158
|
-
rescue TypeError
|
159
|
-
raise ArgumentError, "bad uri"
|
160
155
|
end
|
161
156
|
|
162
|
-
#
|
157
|
+
# normalize URI() behavior across Ruby versions
|
158
|
+
def self.URI url
|
159
|
+
url.respond_to?(:host) ? url :
|
160
|
+
url.respond_to?(:to_str) ? Kernel.URI(url) :
|
161
|
+
raise(ArgumentError, "bad argument (expected URI object or URI string)")
|
162
|
+
end
|
163
|
+
|
164
|
+
def_delegators :url_prefix, :scheme, :scheme=, :host, :host=, :port, :port=
|
165
|
+
def_delegator :url_prefix, :path, :path_prefix
|
166
|
+
|
167
|
+
# Parses the giving url with URI and stores the individual
|
163
168
|
# components in this connection. These components serve as defaults for
|
164
169
|
# requests made by this connection.
|
165
170
|
#
|
@@ -171,27 +176,27 @@ module Faraday
|
|
171
176
|
# conn.get("nigiri?page=2") # accesses https://sushi.com/api/nigiri
|
172
177
|
#
|
173
178
|
def url_prefix=(url)
|
174
|
-
uri
|
175
|
-
self.scheme = uri.scheme
|
176
|
-
self.host = uri.host
|
177
|
-
self.port = uri.port
|
179
|
+
uri = @url_prefix = self.class.URI(url)
|
178
180
|
self.path_prefix = uri.path
|
179
181
|
|
180
|
-
|
182
|
+
params.merge_query(uri.query)
|
183
|
+
uri.query = nil
|
184
|
+
|
181
185
|
if uri.user && uri.password
|
182
186
|
basic_auth(CGI.unescape(uri.user), CGI.unescape(uri.password))
|
187
|
+
uri.user = uri.password = nil
|
183
188
|
end
|
184
189
|
|
185
190
|
uri
|
186
191
|
end
|
187
192
|
|
188
|
-
# Ensures that the path prefix always has a leading
|
193
|
+
# Ensures that the path prefix always has a leading but no trailing slash
|
189
194
|
def path_prefix=(value)
|
190
|
-
if value
|
191
|
-
value.chomp
|
192
|
-
value
|
195
|
+
url_prefix.path = if value
|
196
|
+
value = value.chomp '/'
|
197
|
+
value = '/' + value unless value[0,1] == '/'
|
198
|
+
value
|
193
199
|
end
|
194
|
-
@path_prefix = value
|
195
200
|
end
|
196
201
|
|
197
202
|
def run_request(method, url, body, headers)
|
@@ -199,7 +204,7 @@ module Faraday
|
|
199
204
|
raise ArgumentError, "unknown http method: #{method}"
|
200
205
|
end
|
201
206
|
|
202
|
-
request =
|
207
|
+
request = build_request(method) do |req|
|
203
208
|
req.url(url) if url
|
204
209
|
req.headers.update(headers) if headers
|
205
210
|
req.body = body if body
|
@@ -210,6 +215,18 @@ module Faraday
|
|
210
215
|
self.app.call(env)
|
211
216
|
end
|
212
217
|
|
218
|
+
# Internal: Creates and configures the request object.
|
219
|
+
#
|
220
|
+
# Returns the new Request.
|
221
|
+
def build_request(method)
|
222
|
+
Request.create(method) do |req|
|
223
|
+
req.params = self.params.dup
|
224
|
+
req.headers = self.headers.dup
|
225
|
+
req.options = self.options.merge(:proxy => self.proxy)
|
226
|
+
yield req if block_given?
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
213
230
|
# Takes a relative url for a request and combines it with the defaults
|
214
231
|
# set on the connection instance.
|
215
232
|
#
|
@@ -222,20 +239,32 @@ module Faraday
|
|
222
239
|
# conn.build_url("nigiri", :page => 2) # => https://sushi.com/api/nigiri?token=abc&page=2
|
223
240
|
#
|
224
241
|
def build_url(url, extra_params = nil)
|
225
|
-
uri
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
end
|
231
|
-
uri.host ||= @host
|
232
|
-
uri.port ||= @port
|
233
|
-
uri.scheme ||= @scheme
|
242
|
+
uri = build_exclusive_url(url)
|
243
|
+
|
244
|
+
query_values = self.params.dup.merge_query(uri.query)
|
245
|
+
query_values.update extra_params if extra_params
|
246
|
+
uri.query = query_values.empty? ? nil : query_values.to_query
|
234
247
|
|
235
|
-
|
236
|
-
|
237
|
-
uri.query = params.empty? ? nil : params.to_query
|
248
|
+
uri
|
249
|
+
end
|
238
250
|
|
251
|
+
# Internal: Build an absolute URL based on url_prefix.
|
252
|
+
#
|
253
|
+
# url - A String or URI-like object
|
254
|
+
# params - A Faraday::Utils::ParamsHash to replace the query values
|
255
|
+
# of the resulting url (default: nil).
|
256
|
+
#
|
257
|
+
# Returns the resulting URI instance.
|
258
|
+
def build_exclusive_url(url, params = nil)
|
259
|
+
url = nil if url.respond_to?(:empty?) and url.empty?
|
260
|
+
base = url_prefix
|
261
|
+
if url and base.path and base.path !~ /\/$/
|
262
|
+
base = base.dup
|
263
|
+
base.path = base.path + '/' # ensure trailing slash
|
264
|
+
end
|
265
|
+
uri = url ? base + url : base
|
266
|
+
uri.query = params.to_query if params
|
267
|
+
uri.query = nil if uri.query and uri.query.empty?
|
239
268
|
uri
|
240
269
|
end
|
241
270
|
|