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.
@@ -4,14 +4,7 @@ require 'base64'
4
4
 
5
5
  module Faraday
6
6
  class Connection
7
- include Addressable, Rack::Utils
8
-
9
- HEADERS = Hash.new { |h, k| k.respond_to?(:to_str) ? k : k.to_s.capitalize }.update \
10
- :content_type => "Content-Type",
11
- :content_length => "Content-Length",
12
- :accept_charset => "Accept-Charset",
13
- :accept_encoding => "Accept-Encoding"
14
- HEADERS.values.each { |v| v.freeze }
7
+ include Addressable, Faraday::Utils
15
8
 
16
9
  METHODS = Set.new [:get, :post, :put, :delete, :head]
17
10
  METHODS_WITH_BODIES = Set.new [:post, :put]
@@ -38,35 +31,53 @@ module Faraday
38
31
  proxy(options[:proxy])
39
32
  merge_params @params, options[:params] if options[:params]
40
33
  merge_headers @headers, options[:headers] if options[:headers]
34
+
41
35
  if block
42
- @builder = Builder.create(&block)
36
+ @builder = Builder.new
37
+ @builder.build { block.call(self) }
43
38
  else
44
39
  @builder = options[:builder] || Builder.new
45
40
  end
46
41
  end
47
42
 
43
+ def use(klass, *args, &block)
44
+ @builder.use(klass, *args, &block)
45
+ end
46
+
47
+ def request(key, *args, &block)
48
+ @builder.request(key, *args, &block)
49
+ end
50
+
51
+ def response(key, *args, &block)
52
+ @builder.response(key, *args, &block)
53
+ end
54
+
55
+ def adapter(key, *args, &block)
56
+ @builder.adapter(key, *args, &block)
57
+ end
58
+
48
59
  def build(options = {}, &block)
49
60
  @builder.build(options, &block)
50
61
  end
51
62
 
52
63
  def get(url = nil, headers = nil, &block)
53
- run_request :get, url, nil, headers, &block
64
+ run_request(:get, url, nil, headers, &block)
54
65
  end
55
66
 
56
67
  def post(url = nil, body = nil, headers = nil, &block)
57
- run_request :post, url, body, headers, &block
68
+ run_request(:post, url, body, headers, &block)
58
69
  end
59
70
 
60
71
  def put(url = nil, body = nil, headers = nil, &block)
61
- run_request :put, url, body, headers, &block
72
+ run_request(:put, url, body, headers, &block)
62
73
  end
63
74
 
64
75
  def head(url = nil, headers = nil, &block)
65
- run_request :head, url, nil, headers, &block
76
+ run_request(:head, url, nil, headers, &block)
66
77
  end
67
78
 
68
79
  def delete(url = nil, headers = nil, &block)
69
- run_request :delete, url, nil, headers, &block
80
+ run_request(:delete, url, nil, headers, &block)
70
81
  end
71
82
 
72
83
  def basic_auth(login, pass)
@@ -98,7 +109,7 @@ module Faraday
98
109
  def proxy(arg = nil)
99
110
  return @proxy if arg.nil?
100
111
 
101
- @proxy =
112
+ @proxy =
102
113
  case arg
103
114
  when String then {:uri => proxy_arg_to_uri(arg)}
104
115
  when URI then {:uri => arg}
@@ -112,7 +123,7 @@ module Faraday
112
123
  end
113
124
 
114
125
  # Parses the giving url with Addressable::URI and stores the individual
115
- # components in this connection. These components serve as defaults for
126
+ # components in this connection. These components serve as defaults for
116
127
  # requests made by this connection.
117
128
  #
118
129
  # conn = Faraday::Connection.new { ... }
@@ -131,6 +142,9 @@ module Faraday
131
142
  if uri.query && !uri.query.empty?
132
143
  merge_params @params, parse_query(uri.query)
133
144
  end
145
+ if uri.user && uri.password
146
+ basic_auth(uri.user, uri.password)
147
+ end
134
148
  end
135
149
 
136
150
  # Ensures that the path prefix always has a leading / and no trailing /
@@ -160,7 +174,7 @@ module Faraday
160
174
  end
161
175
  end
162
176
 
163
- # Takes a relative url for a request and combines it with the defaults
177
+ # Takes a relative url for a request and combines it with the defaults
164
178
  # set on the connection instance.
165
179
  #
166
180
  # conn = Faraday::Connection.new { ... }
@@ -190,42 +204,15 @@ module Faraday
190
204
  def replace_query(uri, params)
191
205
  url_params = @params.dup
192
206
  if uri.query && !uri.query.empty?
193
- merge_params url_params, parse_query(uri.query)
207
+ merge_params(url_params, parse_query(uri.query))
194
208
  end
195
209
  if params && !params.empty?
196
- merge_params url_params, params
210
+ merge_params(url_params, params)
197
211
  end
198
212
  uri.query = url_params.empty? ? nil : build_query(url_params)
199
213
  uri
200
214
  end
201
215
 
202
- # turns param keys into strings
203
- def merge_params(existing_params, new_params)
204
- new_params.each do |key, value|
205
- existing_params[key.to_s] = value
206
- end
207
- end
208
-
209
- # turns headers keys and values into strings. Look up symbol keys in the
210
- # the HEADERS hash.
211
- #
212
- # h = merge_headers(HeaderHash.new, :content_type => 'text/plain')
213
- # h['Content-Type'] # = 'text/plain'
214
- #
215
- def merge_headers(existing_headers, new_headers)
216
- new_headers.each do |key, value|
217
- existing_headers[HEADERS[key]] = value.to_s
218
- end
219
- end
220
-
221
- # Be sure to URI escape '+' symbols to %2B. Otherwise, they get interpreted
222
- # as spaces.
223
- def escape(s)
224
- s.to_s.gsub(/([^a-zA-Z0-9_.-]+)/n) do
225
- '%' << $1.unpack('H2'*bytesize($1)).join('%').tap { |c| c.upcase! }
226
- end
227
- end
228
-
229
216
  def proxy_arg_to_uri(arg)
230
217
  case arg
231
218
  when String then URI.parse(arg)
@@ -1,7 +1,31 @@
1
1
  module Faraday
2
2
  module Error
3
- class ClientError < StandardError; end
3
+ class ClientError < StandardError
4
+ def initialize(exception)
5
+ @inner_exception = exception
6
+ end
7
+
8
+ def message
9
+ @inner_exception.message
10
+ end
11
+
12
+ def backtrace
13
+ @inner_exception.backtrace
14
+ end
15
+
16
+ alias to_str message
17
+
18
+ def to_s
19
+ @inner_exception.to_s
20
+ end
21
+
22
+ def inspect
23
+ @inner_exception.inspect
24
+ end
25
+ end
26
+
4
27
  class ConnectionFailed < ClientError; end
5
28
  class ResourceNotFound < ClientError; end
29
+ class ParsingError < ClientError; end
6
30
  end
7
31
  end
@@ -20,35 +20,5 @@ module Faraday
20
20
  def initialize(app = nil)
21
21
  @app = app
22
22
  end
23
-
24
- # assume that query and fragment are already encoded properly
25
- def full_path_for(path, query = nil, fragment = nil)
26
- full_path = path.dup
27
- if query && !query.empty?
28
- full_path << "?#{query}"
29
- end
30
- if fragment && !fragment.empty?
31
- full_path << "##{fragment}"
32
- end
33
- full_path
34
- end
35
-
36
- def process_body_for_request(env)
37
- # if it's a string, pass it through
38
- return if env[:body].nil? || env[:body].empty? || !env[:body].respond_to?(:each_key)
39
- env[:request_headers]['Content-Type'] ||= 'application/x-www-form-urlencoded'
40
- env[:body] = create_form_params(env[:body])
41
- end
42
-
43
- def create_form_params(params, base = nil)
44
- [].tap do |result|
45
- params.each_key do |key|
46
- key_str = base ? "#{base}[#{key}]" : key
47
- value = params[key]
48
- wee = (value.kind_of?(Hash) ? create_form_params(value, key_str) : "#{key_str}=#{escape(value.to_s)}")
49
- result << wee
50
- end
51
- end.join("&")
52
- end
53
23
  end
54
24
  end
@@ -65,11 +65,11 @@ module Faraday
65
65
  def to_env_hash(connection, request_method)
66
66
  env_headers = connection.headers.dup
67
67
  env_params = connection.params.dup
68
- connection.merge_headers env_headers, headers
69
- connection.merge_params env_params, params
68
+ connection.merge_headers(env_headers, headers)
69
+ connection.merge_params(env_params, params)
70
70
 
71
- { :method => request_method,
72
- :body => body,
71
+ { :method => request_method,
72
+ :body => body,
73
73
  :url => connection.build_url(path, env_params),
74
74
  :request_headers => env_headers.update(headers),
75
75
  :parallel_manager => connection.parallel_manager,
@@ -84,4 +84,4 @@ module Faraday
84
84
  app.call(env)
85
85
  end
86
86
  end
87
- end
87
+ end
@@ -13,7 +13,7 @@ module Faraday
13
13
  def call(env)
14
14
  env[:request_headers]['Content-Type'] = 'application/json'
15
15
  if env[:body] && !env[:body].respond_to?(:to_str)
16
- env[:body] = ActiveSupport::JSON.encode env[:body]
16
+ env[:body] = ActiveSupport::JSON.encode(env[:body])
17
17
  end
18
18
  @app.call env
19
19
  end
@@ -10,7 +10,7 @@ module Faraday
10
10
  def call(env)
11
11
  env[:request_headers]['Content-Type'] = 'application/json'
12
12
  if env[:body] && !env[:body].respond_to?(:to_str)
13
- env[:body] = Yajl::Encoder.encode env[:body]
13
+ env[:body] = Yajl::Encoder.encode(env[:body])
14
14
  end
15
15
  @app.call env
16
16
  end
@@ -8,16 +8,23 @@ module Faraday
8
8
 
9
9
  def self.register_on_complete(env)
10
10
  env[:response].on_complete do |finished_env|
11
- finished_env[:body] = ActiveSupport::JSON.decode(finished_env[:body])
11
+ finished_env[:body] = parse(finished_env[:body])
12
+
12
13
  end
13
14
  end
14
15
  rescue LoadError, NameError => e
15
16
  self.load_error = e
16
17
  end
17
-
18
+
18
19
  def initialize(app)
19
20
  super
20
21
  @parser = nil
21
22
  end
23
+
24
+ def self.parse(body)
25
+ ActiveSupport::JSON.decode(body)
26
+ rescue Object => err
27
+ raise Faraday::Error::ParsingError.new(err)
28
+ end
22
29
  end
23
30
  end
@@ -5,16 +5,22 @@ module Faraday
5
5
 
6
6
  def self.register_on_complete(env)
7
7
  env[:response].on_complete do |finished_env|
8
- finished_env[:body] = Yajl::Parser.parse(finished_env[:body])
8
+ finished_env[:body] = parse(finished_env[:body])
9
9
  end
10
10
  end
11
11
  rescue LoadError, NameError => e
12
12
  self.load_error = e
13
13
  end
14
-
14
+
15
15
  def initialize(app)
16
16
  super
17
17
  @parser = nil
18
18
  end
19
+
20
+ def self.parse(body)
21
+ Yajl::Parser.parse(body)
22
+ rescue Object => err
23
+ raise Faraday::Error::ParsingError.new(err)
24
+ end
19
25
  end
20
26
  end
@@ -0,0 +1,15 @@
1
+ begin
2
+ require 'composite_io'
3
+ require 'parts'
4
+ require 'stringio'
5
+ rescue LoadError
6
+ puts "Install the multipart-post gem."
7
+ raise
8
+ end
9
+
10
+ # Auto-load multipart-post gem on first request.
11
+ module Faraday
12
+ CompositeReadIO = ::CompositeReadIO
13
+ UploadIO = ::UploadIO
14
+ Parts = ::Parts
15
+ end
@@ -0,0 +1,64 @@
1
+ require 'rack/utils'
2
+ module Faraday
3
+ module Utils
4
+ include Rack::Utils
5
+
6
+ extend Rack::Utils
7
+ extend self
8
+
9
+ HEADERS = Hash.new do |h, k|
10
+ if k.respond_to?(:to_str)
11
+ k
12
+ else
13
+ k.to_s.split('_'). # :user_agent => %w(user agent)
14
+ each { |w| w.capitalize! }. # => %w(User Agent)
15
+ join('-') # => "User-Agent"
16
+ end
17
+ end
18
+
19
+ HEADERS.merge! :etag => "ETag"
20
+ HEADERS.values.each { |v| v.freeze }
21
+
22
+ # Make Rack::Utils build_query method public.
23
+ public :build_query
24
+
25
+ # Be sure to URI escape '+' symbols to %2B. Otherwise, they get interpreted
26
+ # as spaces.
27
+ def escape(s)
28
+ s.to_s.gsub(/([^a-zA-Z0-9_.-]+)/n) do
29
+ '%' << $1.unpack('H2'*bytesize($1)).join('%').tap { |c| c.upcase! }
30
+ end
31
+ end
32
+
33
+ # Turns param keys into strings
34
+ def merge_params(existing_params, new_params)
35
+ new_params.each do |key, value|
36
+ existing_params[key.to_s] = value
37
+ end
38
+ end
39
+
40
+ # Turns headers keys and values into strings. Look up symbol keys in the
41
+ # the HEADERS hash.
42
+ #
43
+ # h = merge_headers(HeaderHash.new, :content_type => 'text/plain')
44
+ # h['Content-Type'] # = 'text/plain'
45
+ #
46
+ def merge_headers(existing_headers, new_headers)
47
+ new_headers.each do |key, value|
48
+ existing_headers[HEADERS[key]] = value.to_s
49
+ end
50
+ end
51
+
52
+ # Receives a URL and returns just the path with the query string sorted.
53
+ def normalize_path(url)
54
+ (url.path != "" ? url.path : "/") +
55
+ (url.query ? "?#{sort_query_params(url.query)}" : "")
56
+ end
57
+
58
+ protected
59
+
60
+ def sort_query_params(query)
61
+ query.split('&').sort.join('&')
62
+ end
63
+ end
64
+ end
@@ -3,7 +3,10 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'helper'))
3
3
  if Faraday::TestCase::LIVE_SERVER
4
4
  module Adapters
5
5
  class LiveTest < Faraday::TestCase
6
- (Faraday::Adapter.all_loaded_constants + [:default]).each do |adapter|
6
+ loaded_adapters = Faraday::Adapter.all_loaded_constants
7
+ loaded_adapters -= [Faraday::Adapter::ActionDispatch]
8
+ loaded_adapters << :default
9
+ loaded_adapters.each do |adapter|
7
10
  define_method "test_#{adapter}_GET_retrieves_the_response_body" do
8
11
  assert_equal 'hello world', create_connection(adapter).get('hello_world').body
9
12
  end
@@ -39,6 +42,15 @@ if Faraday::TestCase::LIVE_SERVER
39
42
  assert_equal 'text/html', create_connection(adapter).post('echo_name').headers['content-type']
40
43
  end
41
44
 
45
+ define_method "test_#{adapter}_POST_sends_files" do
46
+ name = File.join(File.dirname(__FILE__), '..', 'live_server.rb')
47
+ resp = create_connection(adapter).post do |req|
48
+ req.url 'file'
49
+ req.body = {'uploaded_file' => Faraday::UploadIO.new(name, 'text/x-ruby')}
50
+ end
51
+ assert_equal "file live_server.rb text/x-ruby", resp.body
52
+ end
53
+
42
54
  # http://github.com/toland/patron/issues/#issue/9
43
55
  if ENV['FORCE'] || adapter != Faraday::Adapter::Patron
44
56
  define_method "test_#{adapter}_PUT_send_url_encoded_params" do
@@ -62,22 +74,19 @@ if Faraday::TestCase::LIVE_SERVER
62
74
  end
63
75
  end
64
76
 
65
- # http://github.com/pauldix/typhoeus/issues#issue/7
66
- if ENV['FORCE'] || adapter != Faraday::Adapter::Typhoeus
67
- define_method "test_#{adapter}_HEAD_send_url_encoded_params" do
68
- resp = create_connection(adapter).head do |req|
69
- req.url 'hello', 'name' => 'zack'
70
- end
71
- assert_equal 'text/html', resp.headers['content-type']
77
+ define_method "test_#{adapter}_HEAD_send_url_encoded_params" do
78
+ resp = create_connection(adapter).head do |req|
79
+ req.url 'hello', 'name' => 'zack'
72
80
  end
81
+ assert_equal 'text/html', resp.headers['content-type']
82
+ end
73
83
 
74
- define_method "test_#{adapter}_HEAD_retrieves_no_response_body" do
75
- assert_equal '', create_connection(adapter).head('hello_world').body.to_s
76
- end
84
+ define_method "test_#{adapter}_HEAD_retrieves_no_response_body" do
85
+ assert_equal '', create_connection(adapter).head('hello_world').body.to_s
86
+ end
77
87
 
78
- define_method "test_#{adapter}_HEAD_retrieves_the_response_headers" do
79
- assert_equal 'text/html', create_connection(adapter).head('hello_world').headers['content-type']
80
- end
88
+ define_method "test_#{adapter}_HEAD_retrieves_the_response_headers" do
89
+ assert_equal 'text/html', create_connection(adapter).head('hello_world').headers['content-type']
81
90
  end
82
91
 
83
92
  define_method "test_#{adapter}_DELETE_retrieves_the_response_headers" do
@@ -95,7 +104,7 @@ if Faraday::TestCase::LIVE_SERVER
95
104
  assert !connection.in_parallel?
96
105
  assert_equal 'hello world', connection.get('hello_world').body
97
106
  end
98
-
107
+
99
108
  define_method "test_#{adapter}_async_requests_uses_parallel_manager_to_run_multiple_json_requests" do
100
109
  resp1, resp2 = nil, nil
101
110