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
data/lib/faraday/error.rb
CHANGED
@@ -1,28 +1,33 @@
|
|
1
1
|
module Faraday
|
2
2
|
module Error
|
3
3
|
class ClientError < StandardError
|
4
|
-
|
5
|
-
@inner_exception = exception
|
6
|
-
end
|
4
|
+
attr_reader :response
|
7
5
|
|
8
|
-
def
|
9
|
-
@
|
10
|
-
|
11
|
-
@inner_exception.to_s
|
12
|
-
end
|
6
|
+
def initialize(ex)
|
7
|
+
@wrapped_exception = nil
|
8
|
+
@response = nil
|
13
9
|
|
14
|
-
|
15
|
-
|
10
|
+
if ex.respond_to?(:backtrace)
|
11
|
+
super(ex.message)
|
12
|
+
@wrapped_exception = ex
|
13
|
+
elsif ex.respond_to?(:each_key)
|
14
|
+
super("the server responded with status #{ex[:status]}")
|
15
|
+
@response = ex
|
16
|
+
else
|
17
|
+
super(ex.to_s)
|
18
|
+
end
|
16
19
|
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
def backtrace
|
22
|
+
if @wrapped_exception
|
23
|
+
@wrapped_exception.backtrace
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
22
27
|
end
|
23
28
|
|
24
29
|
def inspect
|
25
|
-
|
30
|
+
%(#<#{self.class}>)
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
data/lib/faraday/middleware.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module Faraday
|
2
2
|
class Middleware
|
3
|
-
include Rack::Utils
|
4
|
-
|
5
3
|
class << self
|
6
4
|
attr_accessor :load_error, :supports_parallel_requests
|
7
5
|
alias supports_parallel_requests? supports_parallel_requests
|
@@ -13,6 +11,13 @@ module Faraday
|
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
14
|
+
# Executes a block which should try to require and reference dependent libraries
|
15
|
+
def self.dependency(lib = nil)
|
16
|
+
lib ? require(lib) : yield
|
17
|
+
rescue LoadError, NameError => error
|
18
|
+
self.load_error = error
|
19
|
+
end
|
20
|
+
|
16
21
|
def self.loaded?
|
17
22
|
@load_error.nil?
|
18
23
|
end
|
data/lib/faraday/request.rb
CHANGED
@@ -11,15 +11,16 @@ module Faraday
|
|
11
11
|
#
|
12
12
|
class Request < Struct.new(:path, :params, :headers, :body)
|
13
13
|
extend AutoloadHelper
|
14
|
+
|
14
15
|
autoload_all 'faraday/request',
|
15
|
-
:
|
16
|
-
:
|
16
|
+
:JSON => 'json',
|
17
|
+
:UrlEncoded => 'url_encoded',
|
18
|
+
:Multipart => 'multipart'
|
17
19
|
|
18
20
|
register_lookup_modules \
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:active_support_json => :ActiveSupportJson
|
21
|
+
:json => :JSON,
|
22
|
+
:url_encoded => :UrlEncoded,
|
23
|
+
:multipart => :Multipart
|
23
24
|
|
24
25
|
def self.run(connection, request_method)
|
25
26
|
req = create
|
@@ -54,7 +55,6 @@ module Faraday
|
|
54
55
|
# :request_headers - hash of HTTP Headers to be sent to the server
|
55
56
|
# :response_headers - Hash of HTTP headers from the server
|
56
57
|
# :parallel_manager - sent if the connection is in parallel mode
|
57
|
-
# :response - the actual response object that stores the rack response
|
58
58
|
# :request - Hash of options for configuring the request.
|
59
59
|
# :timeout - open/read timeout Integer in seconds
|
60
60
|
# :open_timeout - read timeout Integer in seconds
|
@@ -74,15 +74,18 @@ module Faraday
|
|
74
74
|
:url => connection.build_url(path, env_params),
|
75
75
|
:request_headers => env_headers,
|
76
76
|
:parallel_manager => connection.parallel_manager,
|
77
|
-
:response => Response.new,
|
78
77
|
:request => connection.options.merge(:proxy => connection.proxy),
|
79
78
|
:ssl => connection.ssl}
|
80
79
|
end
|
81
80
|
|
82
81
|
def run(connection, request_method)
|
83
|
-
app =
|
82
|
+
app = lambda { |env|
|
83
|
+
response = Response.new
|
84
|
+
response.finish(env) unless env[:parallel_manager]
|
85
|
+
env[:response] = response
|
86
|
+
}
|
84
87
|
env = to_env_hash(connection, request_method)
|
85
|
-
app.call(env)
|
88
|
+
connection.builder.to_app(app).call(env)
|
86
89
|
end
|
87
90
|
end
|
88
91
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Request::JSON < Request::UrlEncoded
|
3
|
+
self.mime_type = 'application/json'.freeze
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :adapter
|
7
|
+
end
|
8
|
+
|
9
|
+
# loads the JSON encoder either from yajl-ruby or activesupport
|
10
|
+
dependency do
|
11
|
+
begin
|
12
|
+
require 'yajl'
|
13
|
+
self.adapter = Yajl::Encoder
|
14
|
+
rescue LoadError, NameError
|
15
|
+
require 'active_support/core_ext/module/attribute_accessors' # AS 2.3.11
|
16
|
+
require 'active_support/core_ext/kernel/reporting' # AS 2.3.11
|
17
|
+
require 'active_support/json/encoding'
|
18
|
+
require 'active_support/ordered_hash' # AS 3.0.4
|
19
|
+
self.adapter = ActiveSupport::JSON
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(env)
|
24
|
+
match_content_type(env) do |data|
|
25
|
+
# encode with the first successfully loaded adapter
|
26
|
+
env[:body] = self.class.adapter.encode data
|
27
|
+
end
|
28
|
+
@app.call env
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Request::Multipart < Request::UrlEncoded
|
3
|
+
self.mime_type = 'multipart/form-data'.freeze
|
4
|
+
DEFAULT_BOUNDARY = "-----------RubyMultipartPost".freeze
|
5
|
+
|
6
|
+
def call(env)
|
7
|
+
match_content_type(env) do |params|
|
8
|
+
env[:request] ||= {}
|
9
|
+
env[:request][:boundary] ||= DEFAULT_BOUNDARY
|
10
|
+
env[:request_headers][CONTENT_TYPE] += ";boundary=#{env[:request][:boundary]}"
|
11
|
+
env[:body] = create_multipart(env, params)
|
12
|
+
end
|
13
|
+
@app.call env
|
14
|
+
end
|
15
|
+
|
16
|
+
def process_request?(env)
|
17
|
+
type = request_type(env)
|
18
|
+
env[:body].respond_to?(:each_key) and !env[:body].empty? and (
|
19
|
+
(type.empty? and has_multipart?(env[:body])) or
|
20
|
+
type == self.class.mime_type
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def has_multipart?(body)
|
25
|
+
body.values.each do |val|
|
26
|
+
if val.respond_to?(:content_type)
|
27
|
+
return true
|
28
|
+
elsif val.respond_to?(:values)
|
29
|
+
return true if has_multipart?(val)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_multipart(env, params)
|
36
|
+
boundary = env[:request][:boundary]
|
37
|
+
parts = process_params(params) do |key, value|
|
38
|
+
Faraday::Parts::Part.new(boundary, key, value)
|
39
|
+
end
|
40
|
+
parts << Faraday::Parts::EpiloguePart.new(boundary)
|
41
|
+
|
42
|
+
body = Faraday::CompositeReadIO.new(parts)
|
43
|
+
env[:request_headers]['Content-Length'] = body.length.to_s
|
44
|
+
return body
|
45
|
+
end
|
46
|
+
|
47
|
+
def process_params(params, prefix = nil, pieces = nil, &block)
|
48
|
+
params.inject(pieces || []) do |all, (key, value)|
|
49
|
+
key = "#{prefix}[#{key}]" if prefix
|
50
|
+
|
51
|
+
case value
|
52
|
+
when Array
|
53
|
+
values = value.inject([]) { |a,v| a << [nil, v] }
|
54
|
+
process_params(values, key, all, &block)
|
55
|
+
when Hash
|
56
|
+
process_params(value, key, all, &block)
|
57
|
+
else
|
58
|
+
all << block.call(key, value)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Request::UrlEncoded < Faraday::Middleware
|
3
|
+
CONTENT_TYPE = 'Content-Type'.freeze
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :mime_type
|
7
|
+
end
|
8
|
+
self.mime_type = 'application/x-www-form-urlencoded'.freeze
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
match_content_type(env) do |data|
|
12
|
+
env[:body] = Faraday::Utils.build_nested_query data
|
13
|
+
end
|
14
|
+
@app.call env
|
15
|
+
end
|
16
|
+
|
17
|
+
def match_content_type(env)
|
18
|
+
type = request_type(env)
|
19
|
+
|
20
|
+
if process_request?(env)
|
21
|
+
env[:request_headers][CONTENT_TYPE] ||= self.class.mime_type
|
22
|
+
yield env[:body] unless env[:body].respond_to?(:to_str)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def process_request?(env)
|
27
|
+
type = request_type(env)
|
28
|
+
env[:body] and (type.empty? or type == self.class.mime_type)
|
29
|
+
end
|
30
|
+
|
31
|
+
def request_type(env)
|
32
|
+
type = env[:request_headers][CONTENT_TYPE].to_s
|
33
|
+
type = type.split(';', 2).first if type.index(';')
|
34
|
+
type
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/faraday/response.rb
CHANGED
@@ -1,56 +1,98 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
1
3
|
module Faraday
|
2
4
|
class Response
|
5
|
+
# Used for simple response middleware.
|
3
6
|
class Middleware < Faraday::Middleware
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# env[:response].on_complete do |finished_env|
|
9
|
-
# finished_env[:body] = do_stuff_to(finished_env[:body])
|
10
|
-
# end
|
11
|
-
#
|
12
|
-
def self.register_on_complete(env)
|
7
|
+
def call(env)
|
8
|
+
@app.call(env).on_complete do |env|
|
9
|
+
on_complete(env)
|
10
|
+
end
|
13
11
|
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
# Override this to modify the environment after the response has finished.
|
14
|
+
# Calls the `parse` method if defined
|
15
|
+
def on_complete(env)
|
16
|
+
if respond_to? :parse
|
17
|
+
env[:body] = parse(env[:body])
|
18
|
+
end
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
22
|
+
extend Forwardable
|
21
23
|
extend AutoloadHelper
|
22
24
|
|
23
25
|
autoload_all 'faraday/response',
|
24
|
-
:
|
25
|
-
:
|
26
|
+
:RaiseError => 'raise_error',
|
27
|
+
:Logger => 'logger'
|
26
28
|
|
27
29
|
register_lookup_modules \
|
28
|
-
:
|
29
|
-
:
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def initialize
|
35
|
-
@status, @headers, @body = nil, nil, nil
|
30
|
+
:raise_error => :RaiseError,
|
31
|
+
:logger => :Logger
|
32
|
+
|
33
|
+
def initialize(env = nil)
|
34
|
+
@env = env
|
36
35
|
@on_complete_callbacks = []
|
37
36
|
end
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
attr_reader :env
|
39
|
+
alias_method :to_hash, :env
|
40
|
+
|
41
|
+
def status
|
42
|
+
finished? ? env[:status] : nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def headers
|
46
|
+
finished? ? env[:response_headers] : {}
|
47
|
+
end
|
48
|
+
def_delegator :headers, :[]
|
49
|
+
|
50
|
+
def body
|
51
|
+
finished? ? env[:body] : nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def finished?
|
55
|
+
!!env
|
56
|
+
end
|
57
|
+
|
58
|
+
def on_complete
|
59
|
+
if not finished?
|
60
|
+
@on_complete_callbacks << Proc.new
|
61
|
+
else
|
62
|
+
yield env
|
63
|
+
end
|
64
|
+
return self
|
41
65
|
end
|
42
66
|
|
43
67
|
def finish(env)
|
44
|
-
|
45
|
-
env
|
46
|
-
env
|
47
|
-
|
48
|
-
@status, @headers, @body = env[:status], env[:response_headers], env[:body]
|
49
|
-
self
|
68
|
+
raise "response already finished" if finished?
|
69
|
+
@env = env
|
70
|
+
@on_complete_callbacks.each { |callback| callback.call(env) }
|
71
|
+
return self
|
50
72
|
end
|
51
73
|
|
52
74
|
def success?
|
53
75
|
status == 200
|
54
76
|
end
|
77
|
+
|
78
|
+
# because @on_complete_callbacks cannot be marshalled
|
79
|
+
def marshal_dump
|
80
|
+
!finished? ? nil : {
|
81
|
+
:status => @env[:status], :body => @env[:body],
|
82
|
+
:response_headers => @env[:response_headers]
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def marshal_load(env)
|
87
|
+
@env = env
|
88
|
+
end
|
89
|
+
|
90
|
+
# Expand the env with more properties, without overriding existing ones.
|
91
|
+
# Useful for applying request params after restoring a marshalled Response.
|
92
|
+
def apply_request(request_env)
|
93
|
+
raise "response didn't finish yet" unless finished?
|
94
|
+
@env = request_env.merge @env
|
95
|
+
return self
|
96
|
+
end
|
55
97
|
end
|
56
98
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
class Response::Logger < Response::Middleware
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def initialize(app, logger = nil)
|
8
|
+
super(app)
|
9
|
+
@logger = logger || begin
|
10
|
+
require 'logger'
|
11
|
+
::Logger.new(STDOUT)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
info "#{env[:method]} #{env[:url].to_s}"
|
19
|
+
debug('request') { dump_headers env[:request_headers] }
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_complete(env)
|
24
|
+
info('Status') { env[:status].to_s }
|
25
|
+
debug('response') { dump_headers env[:response_headers] }
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def dump_headers(headers)
|
31
|
+
headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Response::RaiseError < Response::Middleware
|
3
|
+
def on_complete(env)
|
4
|
+
case env[:status]
|
5
|
+
when 404
|
6
|
+
raise Faraday::Error::ResourceNotFound, response_values(env)
|
7
|
+
when 400...600
|
8
|
+
raise Faraday::Error::ClientError, response_values(env)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def response_values(env)
|
13
|
+
{:status => env[:status], :headers => env[:response_headers], :body => env[:body]}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/faraday/upload_io.rb
CHANGED
@@ -3,13 +3,21 @@ begin
|
|
3
3
|
require 'parts'
|
4
4
|
require 'stringio'
|
5
5
|
rescue LoadError
|
6
|
-
puts "Install the multipart-post gem."
|
6
|
+
$stderr.puts "Install the multipart-post gem."
|
7
7
|
raise
|
8
8
|
end
|
9
9
|
|
10
|
-
# Auto-load multipart-post gem on first request.
|
11
10
|
module Faraday
|
12
|
-
CompositeReadIO
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
class CompositeReadIO < ::CompositeReadIO
|
12
|
+
attr_reader :length
|
13
|
+
|
14
|
+
def initialize(parts)
|
15
|
+
@length = parts.inject(0) { |sum, part| sum + part.length }
|
16
|
+
ios = parts.map{ |part| part.to_io }
|
17
|
+
super(*ios)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
UploadIO = ::UploadIO
|
22
|
+
Parts = ::Parts
|
23
|
+
end
|