faraday 0.9.2 → 0.12.2

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.
@@ -7,8 +7,8 @@ module Faraday
7
7
  class NetHttpPersistent < NetHttp
8
8
  dependency 'net/http/persistent'
9
9
 
10
- def with_net_http_connection(env)
11
- if proxy = env[:request][:proxy]
10
+ def net_http_connection(env)
11
+ if (proxy = env[:request][:proxy])
12
12
  proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
13
13
  proxy_uri.user = proxy_uri.password = nil
14
14
  # awful patch for net-http-persistent 2.8 not unescaping user/password
@@ -16,9 +16,10 @@ module Faraday
16
16
  define_method(:user) { proxy[:user] }
17
17
  define_method(:password) { proxy[:password] }
18
18
  end if proxy[:user]
19
+ return Net::HTTP::Persistent.new 'Faraday', proxy_uri
19
20
  end
20
21
 
21
- yield Net::HTTP::Persistent.new 'Faraday', proxy_uri
22
+ Net::HTTP::Persistent.new 'Faraday'
22
23
  end
23
24
 
24
25
  def perform_request(http, env)
@@ -3,18 +3,13 @@ module Faraday
3
3
  class Patron < Faraday::Adapter
4
4
  dependency 'patron'
5
5
 
6
- def initialize(app, &block)
7
- super(app)
8
- @block = block
9
- end
10
-
11
6
  def call(env)
12
7
  super
13
-
14
8
  # TODO: support streaming requests
15
9
  env[:body] = env[:body].read if env[:body].respond_to? :read
16
10
 
17
11
  session = @session ||= create_session
12
+ configure_ssl(session, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl]
18
13
 
19
14
  if req = env[:request]
20
15
  session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
@@ -35,7 +30,10 @@ module Faraday
35
30
  raise Error::ConnectionFailed, $!
36
31
  end
37
32
 
38
- save_response(env, response.status, response.body, response.headers)
33
+ # Remove the "HTTP/1.1 200", leaving just the reason phrase
34
+ reason_phrase = response.status_line.gsub(/^.* \d{3} /, '')
35
+
36
+ save_response(env, response.status, response.body, response.headers, reason_phrase)
39
37
 
40
38
  @app.call env
41
39
  rescue ::Patron::TimeoutError => err
@@ -69,10 +67,17 @@ module Faraday
69
67
 
70
68
  def create_session
71
69
  session = ::Patron::Session.new
72
- session.insecure = true
73
- @block.call(session) if @block
70
+ @config_block.call(session) if @config_block
74
71
  session
75
72
  end
73
+
74
+ def configure_ssl(session, ssl)
75
+ if ssl.fetch(:verify, true)
76
+ session.cacert = ssl[:ca_file]
77
+ else
78
+ session.insecure = true
79
+ end
80
+ end
76
81
  end
77
82
  end
78
83
  end
@@ -1,16 +1,41 @@
1
1
  module Faraday
2
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']
3
+ # Examples
4
+ #
5
+ # test = Faraday::Connection.new do
6
+ # use Faraday::Adapter::Test do |stub|
7
+ # # simply define matcher to match the request
8
+ # stub.get '/resource.json' do
9
+ # # return static content
10
+ # [200, {'Content-Type' => 'application/json'}, 'hi world']
11
+ # end
12
+ #
13
+ # # response with content generated based on request
14
+ # stub.get '/showget' do |env|
15
+ # [200, {'Content-Type' => 'text/plain'}, env[:method].to_s]
16
+ # end
17
+ #
18
+ # # regular expression can be used as matching filter
19
+ # stub.get /\A\/items\/(\d+)\z/ do |env, meta|
20
+ # # in case regular expression is used an instance of MatchData can be received
21
+ # [200, {'Content-Type' => 'text/plain'}, "showing item: #{meta[:match_data][1]}"]
22
+ # end
7
23
  # end
8
24
  # end
9
- # end
10
- #
11
- # resp = test.get '/nigiri/sake.json'
12
- # resp.body # => 'hi world'
25
+ #
26
+ # resp = test.get '/resource.json'
27
+ # resp.body # => 'hi world'
28
+ #
29
+ # resp = test.get '/showget'
30
+ # resp.body # => 'get'
31
+ #
32
+ # resp = test.get '/items/1'
33
+ # resp.body # => 'showing item: 1'
34
+ #
35
+ # resp = test.get '/items/2'
36
+ # resp.body # => 'showing item: 2'
13
37
  #
38
+
14
39
  class Test < Faraday::Adapter
15
40
  attr_accessor :stubs
16
41
 
@@ -33,12 +58,12 @@ module Faraday
33
58
  stack = @stack[request_method]
34
59
  consumed = (@consumed[request_method] ||= [])
35
60
 
36
- if stub = matches?(stack, path, headers, body)
61
+ stub, meta = matches?(stack, path, headers, body)
62
+ if stub
37
63
  consumed << stack.delete(stub)
38
- stub
39
- else
40
- matches?(consumed, path, headers, body)
64
+ return stub, meta
41
65
  end
66
+ matches?(consumed, path, headers, body)
42
67
  end
43
68
 
44
69
  def get(path, headers = {}, &block)
@@ -85,18 +110,22 @@ module Faraday
85
110
  protected
86
111
 
87
112
  def new_stub(request_method, path, headers = {}, body=nil, &block)
88
- normalized_path = Faraday::Utils.normalize_path(path)
113
+ normalized_path = path.is_a?(Regexp) ? path : Faraday::Utils.normalize_path(path)
89
114
  (@stack[request_method] ||= []) << Stub.new(normalized_path, headers, body, block)
90
115
  end
91
116
 
92
117
  def matches?(stack, path, headers, body)
93
- stack.detect { |stub| stub.matches?(path, headers, body) }
118
+ stack.each do |stub|
119
+ match_result, meta = stub.matches?(path, headers, body)
120
+ return stub, meta if match_result
121
+ end
122
+ nil
94
123
  end
95
124
  end
96
125
 
97
126
  class Stub < Struct.new(:path, :params, :headers, :body, :block)
98
127
  def initialize(full, headers, body, block)
99
- path, query = full.split('?')
128
+ path, query = full.respond_to?(:split) ? full.split("?") : full
100
129
  params = query ?
101
130
  Faraday::Utils.parse_nested_query(query) :
102
131
  {}
@@ -108,10 +137,21 @@ module Faraday
108
137
  request_params = request_query ?
109
138
  Faraday::Utils.parse_nested_query(request_query) :
110
139
  {}
111
- request_path == path &&
140
+ # meta is a hash use as carrier
141
+ # that will be yielded to consumer block
142
+ meta = {}
143
+ return path_match?(request_path, meta) &&
112
144
  params_match?(request_params) &&
113
145
  (body.to_s.size.zero? || request_body == body) &&
114
- headers_match?(request_headers)
146
+ headers_match?(request_headers), meta
147
+ end
148
+
149
+ def path_match?(request_path, meta)
150
+ if path.is_a? Regexp
151
+ !!(meta[:match_data] = path.match(request_path))
152
+ else
153
+ path == request_path
154
+ end
115
155
  end
116
156
 
117
157
  def params_match?(request_params)
@@ -146,11 +186,14 @@ module Faraday
146
186
  normalized_path = Faraday::Utils.normalize_path(env[:url])
147
187
  params_encoder = env.request.params_encoder || Faraday::Utils.default_params_encoder
148
188
 
149
- if stub = stubs.match(env[:method], normalized_path, env.request_headers, env[:body])
189
+ stub, meta = stubs.match(env[:method], normalized_path, env.request_headers, env[:body])
190
+ if stub
150
191
  env[:params] = (query = env[:url].query) ?
151
- params_encoder.decode(query) :
152
- {}
153
- status, headers, body = stub.block.call(env)
192
+ params_encoder.decode(query) : {}
193
+ block_arity = stub.block.arity
194
+ status, headers, body = (block_arity >= 0) ?
195
+ stub.block.call(*[env, meta].take(block_arity)) :
196
+ stub.block.call(env, meta)
154
197
  save_response(env, status, body, headers)
155
198
  else
156
199
  raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}"
@@ -30,13 +30,20 @@ module Faraday
30
30
  extend Parallelism
31
31
  self.supports_parallel = false
32
32
 
33
+ def initialize(app = nil, opts = {}, &block)
34
+ super(app)
35
+ @connection_options = opts
36
+ @config_block = block
37
+ end
38
+
33
39
  def call(env)
34
40
  env.clear_body if env.needs_body?
35
41
  end
36
42
 
37
- def save_response(env, status, body, headers = nil)
43
+ def save_response(env, status, body, headers = nil, reason_phrase = nil)
38
44
  env.status = status
39
45
  env.body = body
46
+ env.reason_phrase = reason_phrase && reason_phrase.to_s.strip
40
47
  env.response_headers = Utils::Headers.new.tap do |response_headers|
41
48
  response_headers.update headers unless headers.nil?
42
49
  yield(response_headers) if block_given?
@@ -55,11 +55,11 @@ module Faraday
55
55
  # :user - String (optional)
56
56
  # :password - String (optional)
57
57
  def initialize(url = nil, options = nil)
58
- if url.is_a?(Hash)
59
- options = ConnectionOptions.from(url)
58
+ options = ConnectionOptions.from(options)
59
+
60
+ if url.is_a?(Hash) || url.is_a?(ConnectionOptions)
61
+ options = options.merge(url)
60
62
  url = options.url
61
- else
62
- options = ConnectionOptions.from(options)
63
63
  end
64
64
 
65
65
  @parallel_manager = nil
@@ -81,11 +81,20 @@ module Faraday
81
81
 
82
82
  @proxy = nil
83
83
  proxy(options.fetch(:proxy) {
84
- uri = ENV['http_proxy']
85
- if uri && !uri.empty?
86
- uri = 'http://' + uri if uri !~ /^http/i
87
- uri
84
+ uri = nil
85
+ if URI.parse("").respond_to?(:find_proxy)
86
+ case url
87
+ when String
88
+ uri = URI.parse(url).find_proxy
89
+ when URI
90
+ uri = url.find_proxy
91
+ when nil
92
+ uri = find_default_proxy
93
+ end
94
+ else
95
+ uri = find_default_proxy
88
96
  end
97
+ uri
89
98
  })
90
99
 
91
100
  yield(self) if block_given?
@@ -126,7 +135,7 @@ module Faraday
126
135
  # req.body = JSON.generate(:query => {...})
127
136
  # end
128
137
  #
129
- # Yields a Faraday::Response for further request customizations.
138
+ # Yields a Faraday::Request for further request customizations.
130
139
  # Returns a Faraday::Response.
131
140
  #
132
141
  # Signature
@@ -163,7 +172,7 @@ module Faraday
163
172
  # req.body = JSON.generate(:user => 'kimchy', ...)
164
173
  # end
165
174
  #
166
- # Yields a Faraday::Response for further request customizations.
175
+ # Yields a Faraday::Request for further request customizations.
167
176
  # Returns a Faraday::Response.
168
177
  #
169
178
  # Signature
@@ -358,7 +367,7 @@ module Faraday
358
367
  #
359
368
  # method - The Symbol HTTP method.
360
369
  # url - The String or URI to access.
361
- # body - The String body
370
+ # body - The request body that will eventually be converted to a string.
362
371
  # headers - Hash of unencoded HTTP header key/value pairs.
363
372
  #
364
373
  # Returns a Faraday::Response.
@@ -433,5 +442,14 @@ module Faraday
433
442
  header(*args)
434
443
  headers[Faraday::Request::Authorization::KEY] = header
435
444
  end
445
+
446
+ def find_default_proxy
447
+ warn 'no_proxy is unsupported' if ENV['no_proxy'] || ENV['NO_PROXY']
448
+ uri = ENV['http_proxy']
449
+ if uri && !uri.empty?
450
+ uri = 'http://' + uri if uri !~ /^http/i
451
+ uri
452
+ end
453
+ end
436
454
  end
437
455
  end
data/lib/faraday/error.rb CHANGED
@@ -3,7 +3,7 @@ module Faraday
3
3
  class MissingDependency < Error; end
4
4
 
5
5
  class ClientError < Error
6
- attr_reader :response
6
+ attr_reader :response, :wrapped_exception
7
7
 
8
8
  def initialize(ex, response = nil)
9
9
  @wrapped_exception = nil
@@ -29,7 +29,17 @@ module Faraday
29
29
  end
30
30
 
31
31
  def inspect
32
- %(#<#{self.class}>)
32
+ inner = ''
33
+ if @wrapped_exception
34
+ inner << " wrapped=#{@wrapped_exception.inspect}"
35
+ end
36
+ if @response
37
+ inner << " response=#{@response.inspect}"
38
+ end
39
+ if inner.empty?
40
+ inner << " #{super}"
41
+ end
42
+ %(#<#{self.class}#{inner}>)
33
43
  end
34
44
  end
35
45
 
@@ -18,23 +18,20 @@ module Faraday
18
18
  # Public
19
19
  def update(obj)
20
20
  obj.each do |key, value|
21
- if sub_options = self.class.options_for(key)
22
- value = sub_options.from(value) if value
23
- elsif Hash === value
24
- hash = {}
25
- value.each do |hash_key, hash_value|
26
- hash[hash_key] = hash_value
27
- end
28
- value = hash
21
+ sub_options = self.class.options_for(key)
22
+ if sub_options
23
+ new_value = sub_options.from(value) if value
24
+ elsif value.is_a?(Hash)
25
+ new_value = value.dup
26
+ else
27
+ new_value = value
29
28
  end
30
29
 
31
- self.send("#{key}=", value) unless value.nil?
30
+ self.send("#{key}=", new_value) unless new_value.nil?
32
31
  end
33
32
  self
34
33
  end
35
34
 
36
- alias merge! update
37
-
38
35
  # Public
39
36
  def delete(key)
40
37
  value = send(key)
@@ -48,8 +45,24 @@ module Faraday
48
45
  end
49
46
 
50
47
  # Public
51
- def merge(value)
52
- dup.update(value)
48
+ def merge!(other)
49
+ other.each do |key, other_value|
50
+ self_value = self.send(key)
51
+ sub_options = self.class.options_for(key)
52
+ new_value = (self_value && sub_options && other_value) ? self_value.merge(other_value) : other_value
53
+ self.send("#{key}=", new_value) unless new_value.nil?
54
+ end
55
+ self
56
+ end
57
+
58
+ # Public
59
+ def merge(other)
60
+ dup.merge!(other)
61
+ end
62
+
63
+ # Public
64
+ def deep_dup
65
+ self.class.from(self)
53
66
  end
54
67
 
55
68
  # Public
@@ -189,8 +202,7 @@ module Faraday
189
202
  end
190
203
 
191
204
  class RequestOptions < Options.new(:params_encoder, :proxy, :bind,
192
- :timeout, :open_timeout, :boundary,
193
- :oauth)
205
+ :timeout, :open_timeout, :boundary, :oauth, :context)
194
206
 
195
207
  def []=(key, value)
196
208
  if key && key.to_sym == :proxy
@@ -252,7 +264,8 @@ module Faraday
252
264
  end
253
265
 
254
266
  class Env < Options.new(:method, :body, :url, :request, :request_headers,
255
- :ssl, :parallel_manager, :params, :response, :response_headers, :status)
267
+ :ssl, :parallel_manager, :params, :response, :response_headers, :status,
268
+ :reason_phrase)
256
269
 
257
270
  ContentLength = 'Content-Length'.freeze
258
271
  StatusesWithoutBody = Set.new [204, 304]
@@ -84,6 +84,7 @@ module Faraday
84
84
  use_symbol(Faraday::Middleware, klass, *args, &block)
85
85
  else
86
86
  raise_if_locked
87
+ warn_middleware_after_adapter if adapter_set?
87
88
  @handlers << self.class::Handler.new(klass, *args, &block)
88
89
  end
89
90
  end
@@ -105,6 +106,7 @@ module Faraday
105
106
  def insert(index, *args, &block)
106
107
  raise_if_locked
107
108
  index = assert_index(index)
109
+ warn_middleware_after_adapter if inserting_after_adapter?(index)
108
110
  handler = self.class::Handler.new(*args, &block)
109
111
  @handlers.insert(index, handler)
110
112
  end
@@ -200,6 +202,26 @@ module Faraday
200
202
  raise StackLocked, "can't modify middleware stack after making a request" if locked?
201
203
  end
202
204
 
205
+ def warn_middleware_after_adapter
206
+ warn "WARNING: Unexpected middleware set after the adapter. " \
207
+ "This won't be supported from Faraday 1.0."
208
+ end
209
+
210
+ def adapter_set?
211
+ @handlers.any? { |handler| is_adapter?(handler) }
212
+ end
213
+
214
+ def inserting_after_adapter?(index)
215
+ adapter_index = @handlers.find_index { |handler| is_adapter?(handler) }
216
+ return false if adapter_index.nil?
217
+
218
+ index > adapter_index
219
+ end
220
+
221
+ def is_adapter?(handler)
222
+ handler.klass.ancestors.include? Faraday::Adapter
223
+ end
224
+
203
225
  def use_symbol(mod, key, *args, &block)
204
226
  use(mod.lookup_middleware(key), *args, &block)
205
227
  end