faraday 0.5.7 → 0.6.0
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 +9 -8
- data/README.md +99 -20
- data/faraday.gemspec +9 -11
- data/lib/faraday.rb +1 -1
- data/lib/faraday/adapter.rb +11 -86
- data/lib/faraday/adapter/action_dispatch.rb +3 -12
- data/lib/faraday/adapter/em_synchrony.rb +9 -24
- data/lib/faraday/adapter/excon.rb +7 -19
- data/lib/faraday/adapter/net_http.rb +37 -35
- data/lib/faraday/adapter/patron.rb +16 -23
- data/lib/faraday/adapter/test.rb +4 -10
- data/lib/faraday/adapter/typhoeus.rb +11 -39
- data/lib/faraday/builder.rb +82 -33
- data/lib/faraday/connection.rb +3 -10
- data/lib/faraday/error.rb +20 -15
- data/lib/faraday/middleware.rb +7 -2
- data/lib/faraday/request.rb +13 -10
- data/lib/faraday/request/json.rb +31 -0
- data/lib/faraday/request/multipart.rb +63 -0
- data/lib/faraday/request/url_encoded.rb +37 -0
- data/lib/faraday/response.rb +72 -30
- data/lib/faraday/response/logger.rb +34 -0
- data/lib/faraday/response/raise_error.rb +16 -0
- data/lib/faraday/upload_io.rb +14 -6
- data/lib/faraday/utils.rb +54 -17
- data/test/adapters/live_test.rb +36 -14
- data/test/adapters/logger_test.rb +1 -1
- data/test/adapters/net_http_test.rb +33 -0
- data/test/connection_test.rb +0 -39
- data/test/env_test.rb +84 -6
- data/test/helper.rb +17 -8
- data/test/live_server.rb +19 -17
- data/test/middleware_stack_test.rb +91 -0
- data/test/request_middleware_test.rb +75 -21
- data/test/response_middleware_test.rb +34 -31
- metadata +21 -17
- data/lib/faraday/adapter/logger.rb +0 -32
- data/lib/faraday/request/active_support_json.rb +0 -21
- data/lib/faraday/request/yajl.rb +0 -18
- data/lib/faraday/response/active_support_json.rb +0 -30
- data/lib/faraday/response/yajl.rb +0 -26
- data/test/adapters/typhoeus_test.rb +0 -31
- data/test/connection_app_test.rb +0 -60
- data/test/form_post_test.rb +0 -58
- data/test/multipart_test.rb +0 -48
@@ -1,7 +1,7 @@
|
|
1
1
|
begin
|
2
2
|
require 'net/https'
|
3
3
|
rescue LoadError
|
4
|
-
|
4
|
+
warn "Warning: no such file to load -- net/https. Make sure openssl is installed if you want ssl support"
|
5
5
|
require 'net/http'
|
6
6
|
end
|
7
7
|
|
@@ -10,53 +10,55 @@ module Faraday
|
|
10
10
|
class NetHttp < Faraday::Adapter
|
11
11
|
def call(env)
|
12
12
|
super
|
13
|
+
url = env[:url]
|
14
|
+
req = env[:request]
|
13
15
|
|
14
|
-
|
16
|
+
http = net_http_class(env).new(url.host, url.inferred_port)
|
15
17
|
|
16
|
-
http =
|
17
|
-
if http.use_ssl = is_ssl
|
18
|
+
if http.use_ssl = (url.scheme == 'https' && env[:ssl])
|
18
19
|
ssl = env[:ssl]
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
http.
|
25
|
-
http.key = ssl[:client_key] if ssl[:client_key]
|
26
|
-
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
|
20
|
+
http.verify_mode = ssl[:verify_mode] || ssl.fetch(:verify, true) ?
|
21
|
+
OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
22
|
+
http.cert = ssl[:client_cert] if ssl[:client_cert]
|
23
|
+
http.key = ssl[:client_key] if ssl[:client_key]
|
24
|
+
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
|
25
|
+
http.cert_store = ssl[:cert_store] if ssl[:cert_store]
|
27
26
|
end
|
28
|
-
|
27
|
+
|
29
28
|
http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
|
30
|
-
http.open_timeout = req[:open_timeout]
|
29
|
+
http.open_timeout = req[:open_timeout] if req[:open_timeout]
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
31
|
+
if :get != env[:method]
|
32
|
+
http_request = Net::HTTPGenericRequest.new \
|
33
|
+
env[:method].to_s.upcase, # request method
|
34
|
+
!!env[:body], # is there data
|
35
|
+
true, # does net/http love you, true or false?
|
36
|
+
url.request_uri, # request uri path
|
37
|
+
env[:request_headers] # request headers
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
if env[:body].respond_to?(:read)
|
40
|
+
http_request.body_stream = env[:body]
|
41
|
+
env[:body] = nil
|
42
|
+
end
|
43
43
|
end
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
begin
|
46
|
+
http_response = if :get == env[:method]
|
47
|
+
# prefer `get` to `request` because the former handles gzip (ruby 1.9)
|
48
|
+
http.get url.request_uri, env[:request_headers]
|
49
|
+
else
|
50
|
+
http.request http_request, env[:body]
|
51
|
+
end
|
52
|
+
rescue Errno::ECONNREFUSED
|
53
|
+
raise Error::ConnectionFailed, $!
|
50
54
|
end
|
51
55
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
+
http_response.each_header do |key, value|
|
57
|
+
response_headers(env)[key] = value
|
58
|
+
end
|
59
|
+
env.update :status => http_response.code.to_i, :body => http_response.body
|
56
60
|
|
57
61
|
@app.call env
|
58
|
-
rescue Errno::ECONNREFUSED => e
|
59
|
-
raise Error::ConnectionFailed.new(e)
|
60
62
|
end
|
61
63
|
|
62
64
|
def net_http_class(env)
|
@@ -1,37 +1,30 @@
|
|
1
1
|
module Faraday
|
2
2
|
class Adapter
|
3
3
|
class Patron < Faraday::Adapter
|
4
|
-
|
5
|
-
require 'patron'
|
6
|
-
rescue LoadError, NameError => e
|
7
|
-
self.load_error = e
|
8
|
-
end
|
4
|
+
dependency 'patron'
|
9
5
|
|
10
6
|
def call(env)
|
11
7
|
super
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
# TODO: support streaming requests
|
10
|
+
env[:body] = env[:body].read if env[:body].respond_to? :read
|
11
|
+
|
12
|
+
session = ::Patron::Session.new
|
13
|
+
|
14
|
+
response = begin
|
15
|
+
if Connection::METHODS_WITH_BODIES.include? env[:method]
|
16
|
+
session.send(env[:method], env[:url].to_s, env[:body].to_s, env[:request_headers])
|
17
|
+
else
|
18
|
+
session.send(env[:method], env[:url].to_s, env[:request_headers])
|
19
|
+
end
|
20
|
+
rescue Errno::ECONNREFUSED
|
21
|
+
raise Error::ConnectionFailed, $!
|
17
22
|
end
|
18
|
-
resp = sess.send *args
|
19
23
|
|
20
|
-
env.update
|
21
|
-
|
22
|
-
:response_headers => resp.headers.
|
23
|
-
inject({}) { |memo, (k, v)| memo.update(k.downcase => v) },
|
24
|
-
:body => resp.body
|
24
|
+
env.update :status => response.status, :body => response.body
|
25
|
+
response_headers(env).update response.headers
|
25
26
|
|
26
27
|
@app.call env
|
27
|
-
rescue Errno::ECONNREFUSED
|
28
|
-
raise Error::ConnectionFailed.new(Errno::ECONNREFUSED)
|
29
|
-
end
|
30
|
-
|
31
|
-
# TODO: build in support for multipart streaming if patron supports it.
|
32
|
-
def create_multipart(env, params, boundary = nil)
|
33
|
-
stream = super
|
34
|
-
stream.read
|
35
28
|
end
|
36
29
|
end
|
37
30
|
end
|
data/lib/faraday/adapter/test.rb
CHANGED
@@ -11,7 +11,7 @@ module Faraday
|
|
11
11
|
# resp = test.get '/nigiri/sake.json'
|
12
12
|
# resp.body # => 'hi world'
|
13
13
|
#
|
14
|
-
class Test <
|
14
|
+
class Test < Faraday::Adapter
|
15
15
|
attr_accessor :stubs
|
16
16
|
|
17
17
|
def self.loaded?() false end
|
@@ -105,24 +105,18 @@ module Faraday
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def call(env)
|
108
|
+
super
|
108
109
|
normalized_path = Faraday::Utils.normalize_path(env[:url])
|
109
110
|
|
110
111
|
if stub = stubs.match(env[:method], normalized_path, env[:body])
|
111
112
|
status, headers, body = stub.block.call(env)
|
112
|
-
env.update
|
113
|
-
|
114
|
-
:response_headers => headers,
|
115
|
-
:body => body
|
113
|
+
env.update :status => status, :body => body
|
114
|
+
response_headers(env).update headers
|
116
115
|
else
|
117
116
|
raise "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
|
118
117
|
end
|
119
118
|
@app.call(env)
|
120
119
|
end
|
121
|
-
|
122
|
-
def create_multipart(env, params, boundary = nil)
|
123
|
-
stream = super
|
124
|
-
stream.read
|
125
|
-
end
|
126
120
|
end
|
127
121
|
end
|
128
122
|
end
|
@@ -7,20 +7,19 @@ module Faraday
|
|
7
7
|
options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options)
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
require 'typhoeus'
|
12
|
-
rescue LoadError, NameError => e
|
13
|
-
self.load_error = e
|
14
|
-
end
|
10
|
+
dependency 'typhoeus'
|
15
11
|
|
16
12
|
def call(env)
|
17
13
|
super
|
18
14
|
|
19
|
-
|
15
|
+
# TODO: support streaming requests
|
16
|
+
env[:body] = env[:body].read if env[:body].respond_to? :read
|
17
|
+
|
18
|
+
req = ::Typhoeus::Request.new env[:url].to_s,
|
20
19
|
:method => env[:method],
|
21
20
|
:body => env[:body],
|
22
21
|
:headers => env[:request_headers],
|
23
|
-
:disable_ssl_peer_verification => (env[:ssl][:verify
|
22
|
+
:disable_ssl_peer_verification => (env[:ssl] && !env[:ssl].fetch(:verify, true))
|
24
23
|
|
25
24
|
env_req = env[:request]
|
26
25
|
req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
|
@@ -28,45 +27,18 @@ module Faraday
|
|
28
27
|
|
29
28
|
is_parallel = !!env[:parallel_manager]
|
30
29
|
req.on_complete do |resp|
|
31
|
-
env.update
|
32
|
-
|
33
|
-
|
34
|
-
:body => resp.body
|
35
|
-
env[:response].finish(env) if !is_parallel
|
30
|
+
env.update :status => resp.code, :body => resp.body
|
31
|
+
response_headers(env).parse resp.headers
|
32
|
+
env[:response].finish(env) if is_parallel
|
36
33
|
end
|
37
34
|
|
38
35
|
hydra = env[:parallel_manager] || self.class.setup_parallel_manager
|
39
36
|
hydra.queue req
|
40
|
-
|
41
|
-
if !is_parallel
|
42
|
-
hydra.run
|
43
|
-
end
|
37
|
+
hydra.run unless is_parallel
|
44
38
|
|
45
39
|
@app.call env
|
46
40
|
rescue Errno::ECONNREFUSED
|
47
|
-
raise Error::ConnectionFailed
|
48
|
-
end
|
49
|
-
|
50
|
-
def in_parallel(options = {})
|
51
|
-
@hydra = ::Typhoeus::Hydra.new(options)
|
52
|
-
yield
|
53
|
-
@hydra.run
|
54
|
-
@hydra = nil
|
55
|
-
end
|
56
|
-
|
57
|
-
def parse_response_headers(header_string)
|
58
|
-
return {} unless header_string && !header_string.empty?
|
59
|
-
Hash[*header_string.split(/\r\n/).
|
60
|
-
tap { |a| a.shift }. # drop the HTTP status line
|
61
|
-
map { |h| h.split(/:\s+/,2) }. # split key and value
|
62
|
-
reject { |(k, v)| k.nil? }. # Ignore blank lines
|
63
|
-
map { |(k, v)| [k.downcase, v] }.flatten]
|
64
|
-
end
|
65
|
-
|
66
|
-
# TODO: build in support for multipart streaming if typhoeus supports it.
|
67
|
-
def create_multipart(env, params, boundary = nil)
|
68
|
-
stream = super
|
69
|
-
stream.read
|
41
|
+
raise Error::ConnectionFailed, $!
|
70
42
|
end
|
71
43
|
end
|
72
44
|
end
|
data/lib/faraday/builder.rb
CHANGED
@@ -1,60 +1,84 @@
|
|
1
1
|
module Faraday
|
2
2
|
# Possibly going to extend this a bit.
|
3
3
|
#
|
4
|
-
# Faraday::Connection.new(:url => 'http://sushi.com') do |
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# b.response :yajl # Faraday::Response::Yajl
|
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
|
8
7
|
# end
|
9
8
|
class Builder
|
10
9
|
attr_accessor :handlers
|
11
10
|
|
12
11
|
def self.create
|
13
|
-
|
14
|
-
Builder.new(&block)
|
12
|
+
new { |builder| yield builder }
|
15
13
|
end
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
# borrowed from ActiveSupport::Dependencies::Reference &
|
16
|
+
# ActionDispatch::MiddlewareStack::Middleware
|
17
|
+
class Handler
|
18
|
+
@@constants = Hash.new { |h, k|
|
19
|
+
h[k] = k.respond_to?(:constantize) ? k.constantize : Object.const_get(k)
|
20
|
+
}
|
21
|
+
|
22
|
+
attr_reader :name
|
23
|
+
|
24
|
+
def initialize(klass, *args, &block)
|
25
|
+
@name = klass.to_s
|
26
|
+
@@constants[@name] = klass if klass.respond_to?(:name)
|
27
|
+
@args, @block = args, block
|
28
|
+
end
|
29
|
+
|
30
|
+
def klass() @@constants[@name] end
|
31
|
+
def inspect() @name end
|
32
|
+
|
33
|
+
def ==(other)
|
34
|
+
if other.respond_to? :name
|
35
|
+
klass == other
|
36
|
+
else
|
37
|
+
@name == other.to_s
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def build(app)
|
42
|
+
klass.new(app, *@args, &@block)
|
20
43
|
end
|
21
44
|
end
|
22
45
|
|
23
46
|
def initialize(handlers = [])
|
24
47
|
@handlers = handlers
|
25
|
-
|
48
|
+
if block_given?
|
49
|
+
build(&Proc.new)
|
50
|
+
elsif @handlers.empty?
|
51
|
+
# default stack, if nothing else is configured
|
52
|
+
self.request :url_encoded
|
53
|
+
self.adapter Faraday.default_adapter
|
54
|
+
end
|
26
55
|
end
|
27
56
|
|
28
57
|
def build(options = {})
|
29
|
-
|
30
|
-
if !options[:keep]
|
31
|
-
@handlers.clear
|
32
|
-
end
|
58
|
+
@handlers.clear unless options[:keep]
|
33
59
|
yield self if block_given?
|
34
|
-
run(inner || self.class.inner_app)
|
35
60
|
end
|
36
61
|
|
37
|
-
def [](
|
38
|
-
|
39
|
-
@handlers[-(index+1)]
|
62
|
+
def [](idx)
|
63
|
+
@handlers[idx]
|
40
64
|
end
|
41
65
|
|
42
|
-
def
|
43
|
-
@handlers.
|
66
|
+
def ==(other)
|
67
|
+
other.is_a?(self.class) && @handlers == other.handlers
|
44
68
|
end
|
45
69
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
end
|
70
|
+
def dup
|
71
|
+
self.class.new(@handlers.dup)
|
72
|
+
end
|
50
73
|
|
51
|
-
|
52
|
-
|
74
|
+
def to_app(inner_app)
|
75
|
+
# last added handler is the deepest and thus closest to the inner app
|
76
|
+
@handlers.reverse.inject(inner_app) { |app, handler| handler.build(app) }
|
53
77
|
end
|
54
78
|
|
55
79
|
def use(klass, *args)
|
56
80
|
block = block_given? ? Proc.new : nil
|
57
|
-
|
81
|
+
@handlers << self.class::Handler.new(klass, *args, &block)
|
58
82
|
end
|
59
83
|
|
60
84
|
def request(key, *args)
|
@@ -72,17 +96,42 @@ module Faraday
|
|
72
96
|
use_symbol(Faraday::Adapter, key, *args, &block)
|
73
97
|
end
|
74
98
|
|
99
|
+
## methods to push onto the various positions in the stack:
|
100
|
+
|
101
|
+
def insert(index, *args, &block)
|
102
|
+
index = assert_index(index)
|
103
|
+
handler = self.class::Handler.new(*args, &block)
|
104
|
+
@handlers.insert(index, handler)
|
105
|
+
end
|
106
|
+
|
107
|
+
alias_method :insert_before, :insert
|
108
|
+
|
109
|
+
def insert_after(index, *args, &block)
|
110
|
+
index = assert_index(index)
|
111
|
+
insert(index + 1, *args, &block)
|
112
|
+
end
|
113
|
+
|
114
|
+
def swap(index, *args, &block)
|
115
|
+
index = assert_index(index)
|
116
|
+
@handlers.delete_at(index)
|
117
|
+
insert(index, *args, &block)
|
118
|
+
end
|
119
|
+
|
120
|
+
def delete(handler)
|
121
|
+
@handlers.delete(handler)
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
75
126
|
def use_symbol(mod, key, *args)
|
76
127
|
block = block_given? ? Proc.new : nil
|
77
128
|
use(mod.lookup_module(key), *args, &block)
|
78
129
|
end
|
79
130
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
def dup
|
85
|
-
self.class.new(@handlers.dup)
|
131
|
+
def assert_index(index)
|
132
|
+
idx = index.is_a?(Integer) ? index : @handlers.index(index)
|
133
|
+
raise "No such handler: #{index.inspect}" unless idx
|
134
|
+
idx
|
86
135
|
end
|
87
136
|
end
|
88
137
|
end
|
data/lib/faraday/connection.rb
CHANGED
@@ -22,7 +22,7 @@ module Faraday
|
|
22
22
|
options = url
|
23
23
|
url = options[:url]
|
24
24
|
end
|
25
|
-
@headers =
|
25
|
+
@headers = Headers.new
|
26
26
|
@params = {}
|
27
27
|
@options = options[:request] || {}
|
28
28
|
@ssl = options[:ssl] || {}
|
@@ -33,9 +33,7 @@ module Faraday
|
|
33
33
|
merge_headers @headers, options[:headers] if options[:headers]
|
34
34
|
|
35
35
|
if block_given?
|
36
|
-
|
37
|
-
@builder = Builder.new
|
38
|
-
@builder.build { block.call(self) }
|
36
|
+
@builder = Builder.create { |b| yield b }
|
39
37
|
else
|
40
38
|
@builder = options[:builder] || Builder.new
|
41
39
|
end
|
@@ -121,7 +119,7 @@ module Faraday
|
|
121
119
|
case arg
|
122
120
|
when String then {:uri => proxy_arg_to_uri(arg)}
|
123
121
|
when URI then {:uri => arg}
|
124
|
-
when Hash
|
122
|
+
when Hash
|
125
123
|
if arg[:uri] = proxy_arg_to_uri(arg[:uri])
|
126
124
|
arg
|
127
125
|
else
|
@@ -164,11 +162,6 @@ module Faraday
|
|
164
162
|
@path_prefix = value
|
165
163
|
end
|
166
164
|
|
167
|
-
# return the assembled Rack application for this instance.
|
168
|
-
def to_app
|
169
|
-
@builder.to_app
|
170
|
-
end
|
171
|
-
|
172
165
|
def run_request(method, url, body, headers)
|
173
166
|
if !METHODS.include?(method)
|
174
167
|
raise ArgumentError, "unknown http method: #{method}"
|