faraday 0.4.6 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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