faraday 0.4.6 → 0.5.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.
@@ -1,6 +1,6 @@
1
- require 'rack/utils'
2
-
3
1
  module Faraday
2
+ VERSION = "0.5.0"
3
+
4
4
  class << self
5
5
  attr_accessor :default_adapter
6
6
  attr_writer :default_connection
@@ -42,37 +42,28 @@ module Faraday
42
42
  end
43
43
 
44
44
  def all_loaded_constants
45
- constants.map { |c| const_get(c) }.select { |a| a.loaded? }
45
+ constants.map { |c| const_get(c) }.
46
+ select { |a| a.respond_to?(:loaded?) && a.loaded? }
46
47
  end
47
48
  end
48
49
 
49
50
  extend AutoloadHelper
50
51
 
51
- autoload_all 'faraday',
52
- :Connection => 'connection',
53
- :Middleware => 'middleware',
54
- :Builder => 'builder',
55
- :Request => 'request',
56
- :Response => 'response',
57
- :Error => 'error'
58
-
59
- module Adapter
60
- extend AutoloadHelper
61
- autoload_all 'faraday/adapter',
62
- :NetHttp => 'net_http',
63
- :Typhoeus => 'typhoeus',
64
- :Patron => 'patron',
65
- :Test => 'test'
66
-
67
- register_lookup_modules \
68
- :test => :Test,
69
- :net_http => :NetHttp,
70
- :typhoeus => :Typhoeus,
71
- :patron => :Patron,
72
- :net_http => :NetHttp
73
- end
52
+ autoload_all 'faraday',
53
+ :Middleware => 'middleware',
54
+ :Builder => 'builder',
55
+ :Request => 'request',
56
+ :Response => 'response',
57
+ :CompositeReadIO => 'upload_io',
58
+ :UploadIO => 'upload_io',
59
+ :Parts => 'upload_io'
74
60
  end
75
61
 
62
+ require 'faraday/utils'
63
+ require 'faraday/connection'
64
+ require 'faraday/adapter'
65
+ require 'faraday/error'
66
+
76
67
  # not pulling in active-support JUST for this method.
77
68
  class Object
78
69
  # Yields <code>x</code> to the block, and then returns <code>x</code>.
@@ -0,0 +1,102 @@
1
+ module Faraday
2
+ class Adapter < Middleware
3
+ FORM_TYPE = 'application/x-www-form-urlencoded'.freeze
4
+ MULTIPART_TYPE = 'multipart/form-data'.freeze
5
+ CONTENT_TYPE = 'Content-Type'.freeze
6
+ DEFAULT_BOUNDARY = "-----------RubyMultipartPost".freeze
7
+
8
+ extend AutoloadHelper
9
+ autoload_all 'faraday/adapter',
10
+ :ActionDispatch => 'action_dispatch',
11
+ :NetHttp => 'net_http',
12
+ :Typhoeus => 'typhoeus',
13
+ :Patron => 'patron',
14
+ :Test => 'test'
15
+
16
+ register_lookup_modules \
17
+ :action_dispatch => :ActionDispatch,
18
+ :test => :Test,
19
+ :net_http => :NetHttp,
20
+ :typhoeus => :Typhoeus,
21
+ :patron => :Patron,
22
+ :net_http => :NetHttp
23
+
24
+ def call(env)
25
+ process_body_for_request(env)
26
+ end
27
+
28
+ # Converts a body hash into encoded form params. This is done as late
29
+ # as possible in the request cycle in case some other middleware wants to
30
+ # act on the request before sending it out.
31
+ #
32
+ # env - The current request environment Hash.
33
+ # body - A Hash of keys/values. Strings and empty values will be
34
+ # ignored. Default: env[:body]
35
+ # headers - The Hash of request headers. Default: env[:request_headers]
36
+ #
37
+ # Returns nothing. If the body is processed, it is replaced in the
38
+ # environment for you.
39
+ def process_body_for_request(env, body = env[:body], headers = env[:request_headers])
40
+ return if body.nil? || body.empty? || !body.respond_to?(:each_key)
41
+ if has_multipart?(body)
42
+ env[:request] ||= {}
43
+ env[:request][:boundary] ||= DEFAULT_BOUNDARY
44
+ headers[CONTENT_TYPE] = MULTIPART_TYPE + ";boundary=#{env[:request][:boundary]}"
45
+ env[:body] = create_multipart(env, body)
46
+ else
47
+ type = headers[CONTENT_TYPE]
48
+ headers[CONTENT_TYPE] = FORM_TYPE if type.nil? || type.empty?
49
+ parts = []
50
+ process_to_params(parts, env[:body]) do |key, value|
51
+ "#{key}=#{escape(value.to_s)}"
52
+ end
53
+ env[:body] = parts * "&"
54
+ end
55
+ end
56
+
57
+ def has_multipart?(body)
58
+ body.values.each do |v|
59
+ if v.respond_to?(:content_type)
60
+ return true
61
+ elsif v.respond_to?(:values)
62
+ return true if has_multipart?(v)
63
+ end
64
+ end
65
+ false
66
+ end
67
+
68
+ def create_multipart(env, params, boundary = nil)
69
+ boundary ||= env[:request][:boundary]
70
+ parts = []
71
+ process_to_params(parts, params) do |key, value|
72
+ Faraday::Parts::Part.new(boundary, key, value)
73
+ end
74
+ parts << Faraday::Parts::EpiloguePart.new(boundary)
75
+ env[:request_headers]['Content-Length'] = parts.inject(0) {|sum,i| sum + i.length }.to_s
76
+ Faraday::CompositeReadIO.new(*parts.map{|p| p.to_io })
77
+ end
78
+
79
+ def process_to_params(pieces, params, base = nil, &block)
80
+ params.each do |key, value|
81
+ key_str = base ? "#{base}[#{key}]" : key
82
+ if value.kind_of?(Hash)
83
+ process_to_params(pieces, value, key_str, &block)
84
+ else
85
+ pieces << block.call(key_str, value)
86
+ end
87
+ end
88
+ end
89
+
90
+ # assume that query and fragment are already encoded properly
91
+ def full_path_for(path, query = nil, fragment = nil)
92
+ full_path = path.dup
93
+ if query && !query.empty?
94
+ full_path << "?#{query}"
95
+ end
96
+ if fragment && !fragment.empty?
97
+ full_path << "##{fragment}"
98
+ end
99
+ full_path
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,39 @@
1
+ module Faraday
2
+ class Adapter
3
+ class ActionDispatch < Faraday::Adapter
4
+ attr_reader :session
5
+
6
+ # Initializes a new middleware instance for each request. Instead of
7
+ # initiating an HTTP request with a web server, this adapter calls
8
+ # a Rails 3 app using integration tests.
9
+ #
10
+ # app - The current Faraday request.
11
+ # session - An ActionDispatch::Integration::Session instance.
12
+ #
13
+ # Returns nothing.
14
+ def initialize(app, session)
15
+ super(app)
16
+ @session = session
17
+ @session.reset!
18
+ end
19
+
20
+ def call(env)
21
+ super
22
+ full_path = full_path_for(env[:url].path, env[:url].query, env[:url].fragment)
23
+ @session.__send__(env[:method], full_path, env[:body], env[:request_headers])
24
+ resp = @session.response
25
+ env.update \
26
+ :status => resp.status,
27
+ :response_headers => resp.headers,
28
+ :body => resp.body
29
+ @app.call env
30
+ end
31
+
32
+ # TODO: build in support for multipart streaming if action dispatch supports it.
33
+ def create_multipart(env, params, boundary = nil)
34
+ stream = super
35
+ stream.read
36
+ end
37
+ end
38
+ end
39
+ end
@@ -6,10 +6,10 @@ rescue LoadError
6
6
  end
7
7
 
8
8
  module Faraday
9
- module Adapter
10
- class NetHttp < Middleware
9
+ class Adapter
10
+ class NetHttp < Faraday::Adapter
11
11
  def call(env)
12
- process_body_for_request(env)
12
+ super
13
13
 
14
14
  is_ssl = env[:url].scheme == 'https'
15
15
 
@@ -28,9 +28,21 @@ module Faraday
28
28
  req = env[:request]
29
29
  http.read_timeout = net.open_timeout = req[:timeout] if req[:timeout]
30
30
  http.open_timeout = req[:open_timeout] if req[:open_timeout]
31
-
31
+
32
32
  full_path = full_path_for(env[:url].path, env[:url].query, env[:url].fragment)
33
- http_resp = http.send_request(env[:method].to_s.upcase, full_path, env[:body], env[:request_headers])
33
+ http_req = Net::HTTPGenericRequest.new(
34
+ env[:method].to_s.upcase, # request method
35
+ (env[:body] ? true : false), # is there data
36
+ true, # does net/http love you, true or false?
37
+ full_path, # request uri path
38
+ env[:request_headers]) # request headers
39
+
40
+ if env[:body].respond_to?(:read)
41
+ http_req.body_stream = env[:body]
42
+ env[:body] = nil
43
+ end
44
+
45
+ http_resp = http.request http_req, env[:body]
34
46
 
35
47
  resp_headers = {}
36
48
  http_resp.each_header do |key, value|
@@ -38,13 +50,13 @@ module Faraday
38
50
  end
39
51
 
40
52
  env.update \
41
- :status => http_resp.code.to_i,
42
- :response_headers => resp_headers,
53
+ :status => http_resp.code.to_i,
54
+ :response_headers => resp_headers,
43
55
  :body => http_resp.body
44
56
 
45
57
  @app.call env
46
58
  rescue Errno::ECONNREFUSED
47
- raise Error::ConnectionFailed, "connection refused"
59
+ raise Error::ConnectionFailed.new(Errno::ECONNREFUSED)
48
60
  end
49
61
 
50
62
  def net_http_class(env)
@@ -1,6 +1,6 @@
1
1
  module Faraday
2
- module Adapter
3
- class Patron < Middleware
2
+ class Adapter
3
+ class Patron < Faraday::Adapter
4
4
  begin
5
5
  require 'patron'
6
6
  rescue LoadError, NameError => e
@@ -8,7 +8,7 @@ module Faraday
8
8
  end
9
9
 
10
10
  def call(env)
11
- process_body_for_request(env)
11
+ super
12
12
 
13
13
  sess = ::Patron::Session.new
14
14
  args = [env[:method], env[:url].to_s, env[:request_headers]]
@@ -26,7 +26,13 @@ module Faraday
26
26
 
27
27
  @app.call env
28
28
  rescue Errno::ECONNREFUSED
29
- raise Error::ConnectionFailed, "connection refused"
29
+ raise Error::ConnectionFailed.new(Errno::ECONNREFUSED)
30
+ end
31
+
32
+ # TODO: build in support for multipart streaming if patron supports it.
33
+ def create_multipart(env, params, boundary = nil)
34
+ stream = super
35
+ stream.read
30
36
  end
31
37
  end
32
38
  end
@@ -1,5 +1,5 @@
1
1
  module Faraday
2
- module Adapter
2
+ class Adapter
3
3
  # test = Faraday::Connection.new do
4
4
  # use Faraday::Adapter::Test do |stub|
5
5
  # stub.get '/nigiri/sake.json' do
@@ -19,7 +19,7 @@ module Faraday
19
19
  class Stubs
20
20
  def initialize
21
21
  # {:get => [Stub, Stub]}
22
- @stack = {}
22
+ @stack, @consumed = {}, {}
23
23
  yield self if block_given?
24
24
  end
25
25
 
@@ -29,8 +29,15 @@ module Faraday
29
29
 
30
30
  def match(request_method, path, body)
31
31
  return false if !@stack.key?(request_method)
32
- stub = @stack[request_method].detect { |stub| stub.matches?(path, body) }
33
- @stack[request_method].delete stub
32
+ stack = @stack[request_method]
33
+ consumed = (@consumed[request_method] ||= [])
34
+
35
+ if stub = matches?(stack, path, body)
36
+ consumed << stack.delete(stub)
37
+ stub
38
+ else
39
+ matches?(consumed, path, body)
40
+ end
34
41
  end
35
42
 
36
43
  def get(path, &block)
@@ -53,10 +60,6 @@ module Faraday
53
60
  new_stub(:delete, path, &block)
54
61
  end
55
62
 
56
- def new_stub(request_method, path, body=nil, &block)
57
- (@stack[request_method] ||= []) << Stub.new(path, body, block)
58
- end
59
-
60
63
  # Raises an error if any of the stubbed calls have not been made.
61
64
  def verify_stubbed_calls
62
65
  failed_stubs = []
@@ -69,6 +72,16 @@ module Faraday
69
72
  end
70
73
  raise failed_stubs.join(" ") unless failed_stubs.size == 0
71
74
  end
75
+
76
+ protected
77
+
78
+ def new_stub(request_method, path, body=nil, &block)
79
+ (@stack[request_method] ||= []) << Stub.new(path, body, block)
80
+ end
81
+
82
+ def matches?(stack, path, body)
83
+ stack.detect { |stub| stub.matches?(path, body) }
84
+ end
72
85
  end
73
86
 
74
87
  class Stub < Struct.new(:path, :body, :block)
@@ -81,7 +94,7 @@ module Faraday
81
94
  end
82
95
  end
83
96
 
84
- def initialize app, stubs=nil, &block
97
+ def initialize(app, stubs=nil, &block)
85
98
  super(app)
86
99
  @stubs = stubs || Stubs.new
87
100
  configure(&block) if block
@@ -91,13 +104,8 @@ module Faraday
91
104
  yield stubs
92
105
  end
93
106
 
94
- def request_uri url
95
- (url.path != "" ? url.path : "/") +
96
- (url.query ? "?#{url.query}" : "")
97
- end
98
-
99
107
  def call(env)
100
- if stub = stubs.match(env[:method], request_uri(env[:url]), env[:body])
108
+ if stub = stubs.match(env[:method], Faraday::Utils.normalize_path(env[:url]), env[:body])
101
109
  status, headers, body = stub.block.call(env)
102
110
  env.update \
103
111
  :status => status,
@@ -108,6 +116,11 @@ module Faraday
108
116
  end
109
117
  @app.call(env)
110
118
  end
119
+
120
+ def create_multipart(env, params, boundary = nil)
121
+ stream = super
122
+ stream.read
123
+ end
111
124
  end
112
125
  end
113
126
  end
@@ -1,6 +1,6 @@
1
1
  module Faraday
2
- module Adapter
3
- class Typhoeus < Middleware
2
+ class Adapter
3
+ class Typhoeus < Faraday::Adapter
4
4
  self.supports_parallel_requests = true
5
5
 
6
6
  def self.setup_parallel_manager(options = {})
@@ -14,15 +14,18 @@ module Faraday
14
14
  end
15
15
 
16
16
  def call(env)
17
- process_body_for_request(env)
17
+ super
18
18
 
19
- hydra = env[:parallel_manager] || self.class.setup_parallel_manager
20
- req = ::Typhoeus::Request.new env[:url].to_s,
19
+ req = ::Typhoeus::Request.new env[:url].to_s,
21
20
  :method => env[:method],
22
21
  :body => env[:body],
23
22
  :headers => env[:request_headers],
24
23
  :disable_ssl_peer_verification => (env[:ssl][:verify] == false)
25
24
 
25
+ env_req = env[:request]
26
+ req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
27
+ req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
28
+
26
29
  req.on_complete do |resp|
27
30
  env.update \
28
31
  :status => resp.code,
@@ -31,6 +34,7 @@ module Faraday
31
34
  env[:response].finish(env)
32
35
  end
33
36
 
37
+ hydra = env[:parallel_manager] || self.class.setup_parallel_manager
34
38
  hydra.queue req
35
39
 
36
40
  if !env[:parallel_manager]
@@ -39,7 +43,7 @@ module Faraday
39
43
 
40
44
  @app.call env
41
45
  rescue Errno::ECONNREFUSED
42
- raise Error::ConnectionFailed, "connection refused"
46
+ raise Error::ConnectionFailed.new(Errno::ECONNREFUSED)
43
47
  end
44
48
 
45
49
  def in_parallel(options = {})
@@ -56,6 +60,12 @@ module Faraday
56
60
  map! { |h| h.split(/:\s+/,2) }. # split key and value
57
61
  map! { |(k, v)| [k.downcase, v] }.flatten!]
58
62
  end
63
+
64
+ # TODO: build in support for multipart streaming if typhoeus supports it.
65
+ def create_multipart(env, params, boundary = nil)
66
+ stream = super
67
+ stream.read
68
+ end
59
69
  end
60
70
  end
61
71
  end
@@ -14,7 +14,7 @@ module Faraday
14
14
  end
15
15
 
16
16
  def self.inner_app
17
- lambda do |env|
17
+ lambda do |env|
18
18
  env[:parallel_manager] ? env[:response] : env[:response].finish(env)
19
19
  end
20
20
  end
@@ -56,19 +56,19 @@ module Faraday
56
56
  end
57
57
 
58
58
  def request(key, *args, &block)
59
- use_symbol Faraday::Request, key, *args, &block
59
+ use_symbol(Faraday::Request, key, *args, &block)
60
60
  end
61
61
 
62
62
  def response(key, *args, &block)
63
- use_symbol Faraday::Response, key, *args, &block
63
+ use_symbol(Faraday::Response, key, *args, &block)
64
64
  end
65
65
 
66
66
  def adapter(key, *args, &block)
67
- use_symbol Faraday::Adapter, key, *args, &block
67
+ use_symbol(Faraday::Adapter, key, *args, &block)
68
68
  end
69
69
 
70
70
  def use_symbol(mod, key, *args, &block)
71
- use mod.lookup_module(key), *args, &block
71
+ use(mod.lookup_module(key), *args, &block)
72
72
  end
73
73
 
74
74
  def ==(other)
@@ -76,7 +76,7 @@ module Faraday
76
76
  end
77
77
 
78
78
  def dup
79
- self.class.new @handlers.dup
79
+ self.class.new(@handlers.dup)
80
80
  end
81
81
  end
82
82
  end