faraday 0.7.5 → 0.7.6

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 CHANGED
@@ -9,8 +9,11 @@ group :test do
9
9
  gem 'em-synchrony', '~> 1.0', :require => ['em-synchrony', 'em-synchrony/em-http'], :platforms => :ruby_19
10
10
  gem 'excon', '~> 0.6'
11
11
  gem 'leftright', '~> 0.9', :require => false
12
+ end
13
+
14
+ platforms :ruby do
12
15
  gem 'patron', '~> 0.4'
13
- gem 'typhoeus', '~> 0.2'
16
+ gem 'typhoeus', '~> 0.3'
14
17
  # ActiveSupport::JSON will be used in ruby 1.8 and Yajl in 1.9; this is to test against both adapters
15
18
  gem 'activesupport', '~> 2.3', :require => nil, :platforms => [:ruby_18, :jruby]
16
19
  gem 'yajl-ruby', '~> 1.0', :require => 'yajl', :platforms => :ruby_19
data/Rakefile CHANGED
@@ -81,10 +81,6 @@ end
81
81
 
82
82
  desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
83
83
  task :release => :build do
84
- unless `git branch` =~ /^\* master$/
85
- puts "You must be on the master branch to release!"
86
- exit!
87
- end
88
84
  sh "git commit --allow-empty -a -m 'Release #{version}'"
89
85
  sh "git tag v#{version}"
90
86
  sh "git push origin master"
@@ -12,8 +12,8 @@ Gem::Specification.new do |s|
12
12
  ## If your rubyforge_project name is different, then edit it and comment out
13
13
  ## the sub! line in the Rakefile
14
14
  s.name = 'faraday'
15
- s.version = '0.7.5'
16
- s.date = '2011-10-04'
15
+ s.version = '0.7.6'
16
+ s.date = '2012-01-21'
17
17
  s.rubyforge_project = 'faraday'
18
18
 
19
19
  ## Make sure your summary is short. The description may be as long
@@ -32,12 +32,12 @@ Gem::Specification.new do |s|
32
32
  ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
33
33
  s.require_paths = %w[lib]
34
34
 
35
- s.add_dependency 'addressable', '~> 2.2.6'
36
- s.add_dependency 'multipart-post', '~> 1.1.3'
37
- s.add_dependency 'rack', ['>= 1.1.0', '< 2']
38
- s.add_development_dependency 'rake', '~> 0.9'
39
- s.add_development_dependency 'test-unit', '~> 2.4'
40
- s.add_development_dependency 'webmock', '~> 1.7'
35
+ s.add_dependency 'addressable', '~> 2.2'
36
+ s.add_dependency 'multipart-post', '~> 1.1'
37
+ s.add_dependency 'rack', '~> 1.1'
38
+ s.add_development_dependency 'rake'
39
+ s.add_development_dependency 'test-unit'
40
+ s.add_development_dependency 'webmock'
41
41
 
42
42
  ## Leave this section as-is. It will be automatically generated from the
43
43
  ## contents of your Git repository via the gemspec task. DO NOT REMOVE
@@ -76,6 +76,7 @@ Gem::Specification.new do |s|
76
76
  test/adapters/logger_test.rb
77
77
  test/adapters/net_http_test.rb
78
78
  test/adapters/test_middleware_test.rb
79
+ test/adapters/typhoeus_test.rb
79
80
  test/connection_test.rb
80
81
  test/env_test.rb
81
82
  test/helper.rb
@@ -1,5 +1,5 @@
1
1
  module Faraday
2
- VERSION = "0.7.5"
2
+ VERSION = "0.7.6"
3
3
 
4
4
  class << self
5
5
  attr_accessor :default_adapter
@@ -17,8 +17,7 @@ module Faraday
17
17
 
18
18
  if http.use_ssl = (url.scheme == 'https' && (ssl = env[:ssl]) && true)
19
19
  http.verify_mode = ssl[:verify_mode] || begin
20
- if ssl.fetch(:verify, true)
21
- OpenSSL::SSL::VERIFY_PEER
20
+ if ssl.fetch(:verify, true)
22
21
  # Use the default cert store by default, i.e. system ca certs
23
22
  store = OpenSSL::X509::Store.new
24
23
  store.set_default_paths
@@ -40,11 +39,11 @@ module Faraday
40
39
  http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
41
40
  http.open_timeout = req[:open_timeout] if req[:open_timeout]
42
41
 
43
- if :get != env[:method]
42
+ if :get != env[:method] or env[:body]
44
43
  http_request = Net::HTTPGenericRequest.new \
45
44
  env[:method].to_s.upcase, # request method
46
- !!env[:body], # is there data
47
- true, # does net/http love you, true or false?
45
+ !!env[:body], # is there request body
46
+ :head != env[:method], # is there response body
48
47
  url.request_uri, # request uri path
49
48
  env[:request_headers] # request headers
50
49
 
@@ -55,7 +54,7 @@ module Faraday
55
54
  end
56
55
 
57
56
  begin
58
- http_response = if :get == env[:method]
57
+ http_response = if :get == env[:method] and env[:body].nil?
59
58
  # prefer `get` to `request` because the former handles gzip (ruby 1.9)
60
59
  http.get url.request_uri, env[:request_headers]
61
60
  else
@@ -72,6 +71,8 @@ module Faraday
72
71
  end
73
72
 
74
73
  @app.call env
74
+ rescue Timeout::Error => err
75
+ raise Faraday::Error::TimeoutError, err
75
76
  end
76
77
 
77
78
  def net_http_class(env)
@@ -11,8 +11,13 @@ module Faraday
11
11
 
12
12
  session = ::Patron::Session.new
13
13
 
14
+ if req = env[:request]
15
+ session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
16
+ session.connect_timeout = req[:open_timeout] if req[:open_timeout]
17
+ end
18
+
14
19
  response = begin
15
- data = Connection::METHODS_WITH_BODIES.include?(env[:method]) ? env[:body].to_s : nil
20
+ data = env[:body] ? env[:body].to_s : nil
16
21
  session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data)
17
22
  rescue Errno::ECONNREFUSED
18
23
  raise Error::ConnectionFailed, $!
@@ -21,6 +26,8 @@ module Faraday
21
26
  save_response(env, response.status, response.body, response.headers)
22
27
 
23
28
  @app.call env
29
+ rescue ::Patron::TimeoutError => err
30
+ raise Faraday::Error::TimeoutError, err
24
31
  end
25
32
 
26
33
  if loaded? && defined?(::Patron::Request::VALID_ACTIONS)
@@ -59,10 +59,18 @@ module Faraday
59
59
  new_stub(:put, path, body, &block)
60
60
  end
61
61
 
62
+ def patch(path, body=nil, &block)
63
+ new_stub(:patch, path, body, &block)
64
+ end
65
+
62
66
  def delete(path, &block)
63
67
  new_stub(:delete, path, &block)
64
68
  end
65
69
 
70
+ def options(path, &block)
71
+ new_stub(:options, path, &block)
72
+ end
73
+
66
74
  # Raises an error if any of the stubbed calls have not been made.
67
75
  def verify_stubbed_calls
68
76
  failed_stubs = []
@@ -29,16 +29,16 @@ module Faraday
29
29
  end
30
30
 
31
31
  env_req = env[:request]
32
-
32
+
33
33
  if proxy = env_req[:proxy]
34
34
  req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}"
35
-
35
+
36
36
  if proxy[:username] && proxy[:password]
37
37
  req.proxy_username = proxy[:username]
38
38
  req.proxy_password = proxy[:password]
39
39
  end
40
40
  end
41
-
41
+
42
42
  req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
43
43
  req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
44
44
 
@@ -1,5 +1,6 @@
1
1
  require 'addressable/uri'
2
2
  require 'base64'
3
+ require 'cgi'
3
4
  require 'set'
4
5
  require 'faraday/builder'
5
6
  require 'faraday/request'
@@ -32,7 +33,10 @@ module Faraday
32
33
  @ssl = options[:ssl] || {}
33
34
  @parallel_manager = options[:parallel]
34
35
 
36
+ @path_prefix = @host = @port = @scheme = nil
35
37
  self.url_prefix = url if url
38
+
39
+ @proxy = nil
36
40
  proxy(options[:proxy])
37
41
 
38
42
  @params.update options[:params] if options[:params]
@@ -145,17 +149,14 @@ module Faraday
145
149
  def proxy(arg = nil)
146
150
  return @proxy if arg.nil?
147
151
 
148
- @proxy =
149
- case arg
150
- when String then {:uri => proxy_arg_to_uri(arg)}
151
- when URI then {:uri => arg}
152
- when Hash
153
- if arg[:uri] = proxy_arg_to_uri(arg[:uri])
154
- arg
155
- else
156
- raise ArgumentError, "no :uri option."
157
- end
158
- end
152
+ @proxy = if arg.is_a? Hash
153
+ uri = arg.fetch(:uri) { raise ArgumentError, "no :uri option" }
154
+ arg.merge :uri => URI.parse(uri)
155
+ else
156
+ {:uri => URI.parse(arg)}
157
+ end
158
+ rescue TypeError
159
+ raise ArgumentError, "bad uri"
159
160
  end
160
161
 
161
162
  # Parses the giving url with Addressable::URI and stores the individual
@@ -177,7 +178,9 @@ module Faraday
177
178
  self.path_prefix = uri.path
178
179
 
179
180
  @params.merge_query(uri.query)
180
- basic_auth(uri.user, uri.password) if uri.user && uri.password
181
+ if uri.user && uri.password
182
+ basic_auth(CGI.unescape(uri.user), CGI.unescape(uri.password))
183
+ end
181
184
 
182
185
  uri
183
186
  end
@@ -239,12 +242,5 @@ module Faraday
239
242
  def dup
240
243
  self.class.new(build_url(''), :headers => headers.dup, :params => params.dup, :builder => builder.dup, :ssl => ssl.dup)
241
244
  end
242
-
243
- def proxy_arg_to_uri(arg)
244
- case arg
245
- when String then URI.parse(arg)
246
- when URI then arg
247
- end
248
- end
249
245
  end
250
246
  end
@@ -3,9 +3,9 @@ module Faraday
3
3
  class ClientError < StandardError
4
4
  attr_reader :response
5
5
 
6
- def initialize(ex)
6
+ def initialize(ex, response = nil)
7
7
  @wrapped_exception = nil
8
- @response = nil
8
+ @response = response
9
9
 
10
10
  if ex.respond_to?(:backtrace)
11
11
  super(ex.message)
@@ -34,7 +34,7 @@ module Faraday
34
34
  class ConnectionFailed < ClientError; end
35
35
  class ResourceNotFound < ClientError; end
36
36
  class ParsingError < ClientError; end
37
-
37
+ class TimeoutError < ClientError; end
38
38
  class MissingDependency < StandardError; end
39
39
  end
40
40
  end
@@ -19,11 +19,11 @@ module Faraday
19
19
  end
20
20
 
21
21
  def self.loaded?
22
- @load_error.nil?
22
+ !defined? @load_error or @load_error.nil?
23
23
  end
24
24
 
25
25
  def initialize(app = nil)
26
26
  @app = app
27
27
  end
28
28
  end
29
- end
29
+ end
@@ -21,12 +21,11 @@ module Faraday
21
21
  )
22
22
  end
23
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)
24
+ def has_multipart?(obj)
25
+ # string is an enum in 1.8, returning list of itself
26
+ if obj.respond_to?(:each) && !obj.is_a?(String)
27
+ (obj.respond_to?(:values) ? obj.values : obj).each do |val|
28
+ return true if (val.respond_to?(:content_type) || has_multipart?(val))
30
29
  end
31
30
  end
32
31
  false
@@ -13,10 +13,8 @@ module Faraday
13
13
  end
14
14
  @app.call env
15
15
  end
16
-
16
+
17
17
  def match_content_type(env)
18
- type = request_type(env)
19
-
20
18
  if process_request?(env)
21
19
  env[:request_headers][CONTENT_TYPE] ||= self.class.mime_type
22
20
  yield env[:body] unless env[:body].respond_to?(:to_str)
@@ -5,8 +5,8 @@ module Faraday
5
5
  # Used for simple response middleware.
6
6
  class Middleware < Faraday::Middleware
7
7
  def call(env)
8
- @app.call(env).on_complete do |env|
9
- on_complete(env)
8
+ @app.call(env).on_complete do |environment|
9
+ on_complete(environment)
10
10
  end
11
11
  end
12
12
 
@@ -8,7 +8,7 @@ module Faraday
8
8
  raise Faraday::Error::ClientError, response_values(env)
9
9
  end
10
10
  end
11
-
11
+
12
12
  def response_values(env)
13
13
  {:status => env[:status], :headers => env[:response_headers], :body => env[:body]}
14
14
  end
@@ -10,7 +10,7 @@ end
10
10
  module Faraday
11
11
  class CompositeReadIO < ::CompositeReadIO
12
12
  attr_reader :length
13
-
13
+
14
14
  def initialize(parts)
15
15
  @length = parts.inject(0) { |sum, part| sum + part.length }
16
16
  ios = parts.map{ |part| part.to_io }
@@ -35,7 +35,7 @@ module Faraday
35
35
  return unless header_string && !header_string.empty?
36
36
  header_string.split(/\r\n/).
37
37
  tap { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line
38
- map { |h| h.split(/:\s+/, 2) }.reject { |(k, v)| k.nil? }. # split key and value, ignore blank lines
38
+ map { |h| h.split(/:\s+/, 2) }.reject { |p| p[0].nil? }. # split key and value, ignore blank lines
39
39
  each { |key, value|
40
40
  # join multiple values with a comma
41
41
  if self[key] then self[key] << ', ' << value
@@ -109,10 +109,10 @@ module Faraday
109
109
  def build_nested_query(value, prefix = nil)
110
110
  case value
111
111
  when Array
112
- value.map { |v| build_nested_query(v, "#{prefix}[]") }.join("&")
112
+ value.map { |v| build_nested_query(v, "#{prefix}%5B%5D") }.join("&")
113
113
  when Hash
114
114
  value.map { |k, v|
115
- build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
115
+ build_nested_query(v, prefix ? "#{prefix}%5B#{escape(k)}%5D" : escape(k))
116
116
  }.join("&")
117
117
  when NilClass
118
118
  prefix
@@ -125,8 +125,10 @@ module Faraday
125
125
  # Be sure to URI escape '+' symbols to %2B. Otherwise, they get interpreted
126
126
  # as spaces.
127
127
  def escape(s)
128
- s.to_s.gsub(/([^a-zA-Z0-9_.-]+)/n) do
129
- '%' << $1.unpack('H2'*bytesize($1)).join('%').tap { |c| c.upcase! }
128
+ s = s.to_s
129
+ s = s.dup.force_encoding('binary') if s.respond_to? :force_encoding
130
+ s.gsub(/([^a-zA-Z0-9_.-]+)/n) do |match|
131
+ '%' << match.unpack('H2'*bytesize(match)).join('%').tap { |c| c.upcase! }
130
132
  end
131
133
  end
132
134
 
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'helper'))
1
+ require File.expand_path("../../helper", __FILE__)
2
2
 
3
3
  if !Faraday::TestCase::LIVE_SERVER
4
4
  warn "warning: test server not specified; skipping live server tests"
@@ -10,6 +10,8 @@ else
10
10
  else
11
11
  loaded_adapters = Faraday::Adapter.all_loaded_constants
12
12
  loaded_adapters -= [Faraday::Adapter::ActionDispatch]
13
+ # https://github.com/geemus/excon/issues/98
14
+ loaded_adapters -= [Faraday::Adapter::Excon] if defined? RUBY_ENGINE and "rbx" == RUBY_ENGINE
13
15
  loaded_adapters << :default
14
16
  end
15
17
 
@@ -27,8 +29,8 @@ else
27
29
 
28
30
  define_method "test_#{adapter}_GET_retrieves_the_response_headers" do
29
31
  response = create_connection(adapter).get('hello_world')
30
- assert_match /text\/html/, response.headers['Content-Type'], 'original case fail'
31
- assert_match /text\/html/, response.headers['content-type'], 'lowercase fail'
32
+ assert_match(/text\/html/, response.headers['Content-Type'], 'original case fail')
33
+ assert_match(/text\/html/, response.headers['content-type'], 'lowercase fail')
32
34
  end
33
35
 
34
36
  # https://github.com/geemus/excon/issues/10
@@ -39,6 +41,17 @@ else
39
41
  end
40
42
  end
41
43
 
44
+ # https://github.com/dbalatero/typhoeus/issues/75
45
+ # https://github.com/toland/patron/issues/52
46
+ unless %[Faraday::Adapter::Typhoeus Faraday::Adapter::Patron].include? adapter.to_s
47
+ define_method "test_#{adapter}_GET_with_body" do
48
+ response = create_connection(adapter).get('echo') do |req|
49
+ req.body = {'bodyrock' => true}
50
+ end
51
+ assert_equal %(get {"bodyrock"=>"true"}), response.body
52
+ end
53
+ end
54
+
42
55
  define_method "test_#{adapter}_POST_send_url_encoded_params" do
43
56
  resp = create_connection(adapter).post do |req|
44
57
  req.url 'echo_name'
@@ -56,7 +69,7 @@ else
56
69
  end
57
70
 
58
71
  define_method "test_#{adapter}_POST_retrieves_the_response_headers" do
59
- assert_match /text\/html/, create_connection(adapter).post('echo_name').headers['content-type']
72
+ assert_match(/text\/html/, create_connection(adapter).post('echo_name').headers['content-type'])
60
73
  end
61
74
 
62
75
  define_method "test_#{adapter}_POST_sends_files" do
@@ -90,7 +103,7 @@ else
90
103
  # https://github.com/dbalatero/typhoeus/issues/84
91
104
  if ENV['FORCE'] || !%w[Faraday::Adapter::Patron Faraday::Adapter::Typhoeus].include?(adapter.to_s)
92
105
  define_method "test_#{adapter}_PUT_retrieves_the_response_headers" do
93
- assert_match /text\/html/, create_connection(adapter).put('echo_name').headers['content-type']
106
+ assert_match(/text\/html/, create_connection(adapter).put('echo_name').headers['content-type'])
94
107
  end
95
108
  end
96
109
 
@@ -113,7 +126,7 @@ else
113
126
  resp = create_connection(adapter).head do |req|
114
127
  req.url 'hello', 'name' => 'zack'
115
128
  end
116
- assert_match /text\/html/, resp.headers['content-type']
129
+ assert_match(/text\/html/, resp.headers['content-type'])
117
130
  end
118
131
 
119
132
  define_method "test_#{adapter}_HEAD_retrieves_no_response_body" do
@@ -121,21 +134,21 @@ else
121
134
  end
122
135
 
123
136
  define_method "test_#{adapter}_HEAD_retrieves_the_response_headers" do
124
- assert_match /text\/html/, create_connection(adapter).head('hello_world').headers['content-type']
137
+ assert_match(/text\/html/, create_connection(adapter).head('hello_world').headers['content-type'])
125
138
  end
126
139
 
127
140
  define_method "test_#{adapter}_DELETE_retrieves_the_response_headers" do
128
- assert_match /text\/html/, create_connection(adapter).delete('delete_with_json').headers['content-type']
141
+ assert_match(/text\/html/, create_connection(adapter).delete('delete_with_json').headers['content-type'])
129
142
  end
130
143
 
131
144
  define_method "test_#{adapter}_DELETE_retrieves_the_body" do
132
- assert_match /deleted/, create_connection(adapter).delete('delete_with_json').body
145
+ assert_match(/deleted/, create_connection(adapter).delete('delete_with_json').body)
133
146
  end
134
147
 
135
148
  define_method "test_#{adapter}_async_requests_clear_parallel_manager_after_running_a_single_request" do
136
149
  connection = create_connection(adapter)
137
150
  assert !connection.in_parallel?
138
- resp = connection.get('hello_world')
151
+ connection.get('hello_world')
139
152
  assert !connection.in_parallel?
140
153
  assert_equal 'hello world', connection.get('hello_world').body
141
154
  end
@@ -173,9 +186,18 @@ else
173
186
  end
174
187
  end
175
188
  end
189
+
190
+ if %w[Faraday::Adapter::Patron Faraday::Adapter::NetHttp].include?(adapter.to_s)
191
+ define_method "test_#{adapter}_timeout" do
192
+ conn = create_connection(adapter, :request => {:timeout => 1, :read_timeout => 1})
193
+ assert_raise Faraday::Error::TimeoutError do
194
+ conn.get '/slow'
195
+ end
196
+ end
197
+ end
176
198
  end
177
199
 
178
- def create_connection(adapter)
200
+ def create_connection(adapter, options = {})
179
201
  if adapter == :default
180
202
  builder_block = nil
181
203
  else
@@ -185,8 +207,8 @@ else
185
207
  b.use adapter
186
208
  end
187
209
  end
188
-
189
- Faraday::Connection.new(LIVE_SERVER, &builder_block).tap do |conn|
210
+
211
+ Faraday::Connection.new(LIVE_SERVER, options, &builder_block).tap do |conn|
190
212
  conn.headers['X-Faraday-Adapter'] = adapter.to_s
191
213
  adapter_handler = conn.builder.handlers.last
192
214
  conn.builder.insert_before adapter_handler, Faraday::Response::RaiseError
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'helper'))
2
+
3
+ module Adapters
4
+ class TyphoeusTest < Faraday::TestCase
5
+ def setup
6
+ @connection = Faraday.new('http://disney.com') do |b|
7
+ b.adapter :typhoeus
8
+ end
9
+ end
10
+
11
+ def test_handles_user_agent
12
+ # default typhoeus agent
13
+ stub_request(:get, 'disney.com/world').with(:headers => {'User-Agent'=>'Faraday Agent'}){ |request|
14
+ request.headers["User-Agent"] == 'Faraday Agent'
15
+ }
16
+ @connection.get('/world', :user_agent => 'Faraday Agent')
17
+ end
18
+
19
+ end if defined? ::Typhoeus
20
+ end
@@ -1,4 +1,5 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
+ require 'uri'
2
3
 
3
4
  class TestConnection < Faraday::TestCase
4
5
  def test_initialize_parses_host_out_of_given_url
@@ -73,6 +74,11 @@ class TestConnection < Faraday::TestCase
73
74
  assert_equal 'Basic YWxhZGRpbjpvcGVuc2VzYW1l', conn.headers['Authorization']
74
75
  end
75
76
 
77
+ def test_auto_parses_basic_auth_from_url_and_unescapes
78
+ conn = Faraday::Connection.new :url => "http://foo%40bar.com:pass%20word@sushi.com/fish"
79
+ assert_equal 'Basic Zm9vQGJhci5jb206cGFzcyB3b3Jk', conn.headers['Authorization']
80
+ end
81
+
76
82
  def test_token_auth_sets_authorization_header
77
83
  conn = Faraday::Connection.new
78
84
  conn.token_auth 'abcdef'
@@ -147,13 +153,20 @@ class TestConnection < Faraday::TestCase
147
153
  assert_equal '/sake.html', uri.path
148
154
  end
149
155
 
150
- def test_build_url_doesnt_add_ending_slash
156
+ def test_build_url_doesnt_add_ending_slash_given_nil_url
151
157
  conn = Faraday::Connection.new
152
158
  conn.url_prefix = "http://sushi.com/nigiri"
153
159
  uri = conn.build_url(nil)
154
160
  assert_equal "/nigiri", uri.path
155
161
  end
156
162
 
163
+ def test_build_url_doesnt_add_ending_slash_given_empty_url
164
+ conn = Faraday::Connection.new
165
+ conn.url_prefix = "http://sushi.com/nigiri"
166
+ uri = conn.build_url('')
167
+ assert_equal "/nigiri", uri.path
168
+ end
169
+
157
170
  def test_build_url_parses_url_params_into_query
158
171
  conn = Faraday::Connection.new
159
172
  uri = conn.build_url("http://sushi.com/sake.html", 'a[b]' => '1 + 2')
@@ -196,6 +209,12 @@ class TestConnection < Faraday::TestCase
196
209
  assert_equal 'https://sushi.com/sushi/sake.html', uri.to_s
197
210
  end
198
211
 
212
+ def test_build_url_handles_uri_instances
213
+ conn = Faraday::Connection.new
214
+ uri = conn.build_url(URI('/sake.html'))
215
+ assert_equal '/sake.html', uri.path
216
+ end
217
+
199
218
  def test_proxy_accepts_string
200
219
  conn = Faraday::Connection.new
201
220
  conn.proxy 'http://proxy.com'
@@ -203,13 +222,20 @@ class TestConnection < Faraday::TestCase
203
222
  assert_equal [:uri], conn.proxy.keys
204
223
  end
205
224
 
206
- def test_proxy_accepts_uri
225
+ def test_proxy_accepts_addressable_uri
207
226
  conn = Faraday::Connection.new
208
227
  conn.proxy Addressable::URI.parse('http://proxy.com')
209
228
  assert_equal 'proxy.com', conn.proxy[:uri].host
210
229
  assert_equal [:uri], conn.proxy.keys
211
230
  end
212
231
 
232
+ def test_proxy_accepts_stdlib_uri
233
+ conn = Faraday::Connection.new
234
+ conn.proxy URI('http://proxy.com')
235
+ assert_equal 'proxy.com', conn.proxy[:uri].host
236
+ assert_equal [:uri], conn.proxy.keys
237
+ end
238
+
213
239
  def test_proxy_accepts_hash_with_string_uri
214
240
  conn = Faraday::Connection.new
215
241
  conn.proxy :uri => 'http://proxy.com', :user => 'rick'
@@ -112,45 +112,45 @@ class ResponseTest < Faraday::TestCase
112
112
  }
113
113
  @response = Faraday::Response.new @env
114
114
  end
115
-
115
+
116
116
  def test_finished
117
117
  assert @response.finished?
118
118
  end
119
-
119
+
120
120
  def test_error_on_finish
121
121
  assert_raises RuntimeError do
122
122
  @response.finish({})
123
123
  end
124
124
  end
125
-
125
+
126
126
  def test_not_success
127
127
  assert !@response.success?
128
128
  end
129
-
129
+
130
130
  def test_status
131
131
  assert_equal 404, @response.status
132
132
  end
133
-
133
+
134
134
  def test_body
135
135
  assert_equal 'yikes', @response.body
136
136
  end
137
-
137
+
138
138
  def test_headers
139
139
  assert_equal 'text/plain', @response.headers['Content-Type']
140
140
  assert_equal 'text/plain', @response['content-type']
141
141
  end
142
-
142
+
143
143
  def test_apply_request
144
144
  @response.apply_request :body => 'a=b', :method => :post
145
145
  assert_equal 'yikes', @response.body
146
146
  assert_equal :post, @response.env[:method]
147
147
  end
148
-
148
+
149
149
  def test_marshal
150
150
  @response = Faraday::Response.new
151
151
  @response.on_complete { }
152
152
  @response.finish @env.merge(:custom => 'moo')
153
-
153
+
154
154
  loaded = Marshal.load Marshal.dump(@response)
155
155
  assert_nil loaded.env[:custom]
156
156
  assert_equal %w[body response_headers status], loaded.env.keys.map { |k| k.to_s }.sort
@@ -1,5 +1,5 @@
1
- require 'rubygems'
2
1
  require 'test/unit'
2
+ require 'stringio'
3
3
 
4
4
  if ENV['LEFTRIGHT']
5
5
  begin
@@ -9,10 +9,6 @@ if ENV['LEFTRIGHT']
9
9
  end
10
10
  end
11
11
 
12
- unless $LOAD_PATH.include? 'lib'
13
- $LOAD_PATH.unshift(File.dirname(__FILE__))
14
- $LOAD_PATH.unshift(File.join($LOAD_PATH.first, '..', 'lib'))
15
- end
16
12
  require 'faraday'
17
13
 
18
14
  begin
@@ -28,12 +24,22 @@ module Faraday
28
24
  LIVE_SERVER = case ENV['LIVE']
29
25
  when /^http/ then ENV['LIVE']
30
26
  when nil then nil
31
- else 'http://localhost:4567'
27
+ else 'http://127.0.0.1:4567'
32
28
  end
33
29
 
34
30
  def test_default
35
31
  assert true
36
32
  end unless defined? ::MiniTest
33
+
34
+ def capture_warnings
35
+ old, $stderr = $stderr, StringIO.new
36
+ begin
37
+ yield
38
+ $stderr.string
39
+ ensure
40
+ $stderr = old
41
+ end
42
+ end
37
43
  end
38
44
  end
39
45
 
@@ -1,6 +1,18 @@
1
1
  require 'sinatra'
2
2
  set :logging, false
3
3
 
4
+ [:get, :post, :put, :patch, :delete, :options].each do |method|
5
+ send(method, '/echo') do
6
+ kind = request.request_method.downcase
7
+ out = kind.dup
8
+ out << ' ?' << request.GET.inspect if request.GET.any?
9
+ out << ' ' << request.POST.inspect if request.POST.any?
10
+
11
+ content_type 'text/plain'
12
+ return out
13
+ end
14
+ end
15
+
4
16
  get '/hello_world' do
5
17
  'hello world'
6
18
  end
@@ -41,5 +53,10 @@ delete '/delete_with_json' do
41
53
  end
42
54
 
43
55
  get '/multi' do
44
- [200, { 'Set-Cookie' => %w[ one two ] }, '']
56
+ [200, { 'Set-Cookie' => 'one, two' }, '']
57
+ end
58
+
59
+ get '/slow' do
60
+ sleep 10
61
+ [200, {}, 'ok']
45
62
  end
@@ -1,7 +1,8 @@
1
+ # encoding: utf-8
1
2
  require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
2
3
  require 'rack/utils'
3
4
 
4
- Faraday::CompositeReadIO.send :attr_reader, :ios
5
+ Faraday::CompositeReadIO.class_eval { attr_reader :ios }
5
6
 
6
7
  class RequestMiddlewareTest < Faraday::TestCase
7
8
  def setup
@@ -76,7 +77,7 @@ class RequestMiddlewareTest < Faraday::TestCase
76
77
  def test_url_encoded_no_header
77
78
  response = @conn.post('/echo', { :fruit => %w[apples oranges] })
78
79
  assert_equal 'application/x-www-form-urlencoded', response.headers['Content-Type']
79
- assert_equal 'fruit[]=apples&fruit[]=oranges', response.body
80
+ assert_equal 'fruit%5B%5D=apples&fruit%5B%5D=oranges', response.body
80
81
  end
81
82
 
82
83
  def test_url_encoded_with_header
@@ -92,6 +93,19 @@ class RequestMiddlewareTest < Faraday::TestCase
92
93
  assert_equal expected, Rack::Utils.parse_nested_query(response.body)
93
94
  end
94
95
 
96
+ def test_url_encoded_unicode
97
+ err = capture_warnings {
98
+ response = @conn.post('/echo', {:str => "eé cç aã aâ"})
99
+ assert_equal "str=e%C3%A9%20c%C3%A7%20a%C3%A3%20a%C3%A2", response.body
100
+ }
101
+ assert err.empty?
102
+ end
103
+
104
+ def test_url_encoded_nested_keys
105
+ response = @conn.post('/echo', {'a'=>{'b'=>{'c'=>['d']}}})
106
+ assert_equal "a%5Bb%5D%5Bc%5D%5B%5D=d", response.body
107
+ end
108
+
95
109
  def test_multipart
96
110
  # assume params are out of order
97
111
  regexes = [
@@ -113,4 +127,27 @@ class RequestMiddlewareTest < Faraday::TestCase
113
127
  end
114
128
  assert_equal [], regexes
115
129
  end
130
+
131
+ def test_multipart_with_arrays
132
+ # assume params are out of order
133
+ regexes = [
134
+ /name\=\"a\"/,
135
+ /name=\"b\[\]\[c\]\"\; filename\=\"request_middleware_test\.rb\"/,
136
+ /name=\"b\[\]\[d\]\"/]
137
+
138
+ payload = {:a => 1, :b =>[{:c => Faraday::UploadIO.new(__FILE__, 'text/x-ruby'), :d => 2}]}
139
+ response = @conn.post('/echo', payload)
140
+
141
+ assert_kind_of Faraday::CompositeReadIO, response.body
142
+ assert_equal "multipart/form-data;boundary=%s" % Faraday::Request::Multipart::DEFAULT_BOUNDARY,
143
+ response.headers['Content-Type']
144
+
145
+ response.body.send(:ios).map{|io| io.read}.each do |io|
146
+ if re = regexes.detect { |r| io =~ r }
147
+ regexes.delete re
148
+ end
149
+ end
150
+ assert_equal [], regexes
151
+ end
152
+
116
153
  end
@@ -23,7 +23,7 @@ class ResponseMiddlewareTest < Faraday::TestCase
23
23
  @conn.get('ok')
24
24
  end
25
25
  end
26
-
26
+
27
27
  def test_raises_not_found
28
28
  error = assert_raises Faraday::Error::ResourceNotFound do
29
29
  @conn.get('not-found')
@@ -31,7 +31,7 @@ class ResponseMiddlewareTest < Faraday::TestCase
31
31
  assert_equal 'the server responded with status 404', error.message
32
32
  assert_equal 'because', error.response[:headers]['X-Reason']
33
33
  end
34
-
34
+
35
35
  def test_raises_error
36
36
  error = assert_raises Faraday::Error::ClientError do
37
37
  @conn.get('error')
@@ -39,7 +39,7 @@ class ResponseMiddlewareTest < Faraday::TestCase
39
39
  assert_equal 'the server responded with status 500', error.message
40
40
  assert_equal 'bailout', error.response[:headers]['X-Error']
41
41
  end
42
-
42
+
43
43
  def test_upcase
44
44
  @conn.builder.insert(0, ResponseUpcaser)
45
45
  assert_equal '<BODY></BODY>', @conn.get('ok').body
@@ -71,4 +71,4 @@ class ResponseNoBodyMiddleWareTest < Faraday::TestCase
71
71
  def test_304
72
72
  assert_equal nil, @conn.get('not modified').body
73
73
  end
74
- end
74
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faraday
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
4
+ version: 0.7.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,77 +9,74 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-04 00:00:00.000000000Z
12
+ date: 2012-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: addressable
16
- requirement: &70213347338660 !ruby/object:Gem::Requirement
16
+ requirement: &70207313872560 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 2.2.6
21
+ version: '2.2'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70213347338660
24
+ version_requirements: *70207313872560
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: multipart-post
27
- requirement: &70213347338000 !ruby/object:Gem::Requirement
27
+ requirement: &70207313884640 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
31
31
  - !ruby/object:Gem::Version
32
- version: 1.1.3
32
+ version: '1.1'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70213347338000
35
+ version_requirements: *70207313884640
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rack
38
- requirement: &70213347336580 !ruby/object:Gem::Requirement
38
+ requirement: &70207313889320 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
- - - ! '>='
42
- - !ruby/object:Gem::Version
43
- version: 1.1.0
44
- - - <
41
+ - - ~>
45
42
  - !ruby/object:Gem::Version
46
- version: '2'
43
+ version: '1.1'
47
44
  type: :runtime
48
45
  prerelease: false
49
- version_requirements: *70213347336580
46
+ version_requirements: *70207313889320
50
47
  - !ruby/object:Gem::Dependency
51
48
  name: rake
52
- requirement: &70213347335860 !ruby/object:Gem::Requirement
49
+ requirement: &70207313910400 !ruby/object:Gem::Requirement
53
50
  none: false
54
51
  requirements:
55
- - - ~>
52
+ - - ! '>='
56
53
  - !ruby/object:Gem::Version
57
- version: '0.9'
54
+ version: '0'
58
55
  type: :development
59
56
  prerelease: false
60
- version_requirements: *70213347335860
57
+ version_requirements: *70207313910400
61
58
  - !ruby/object:Gem::Dependency
62
59
  name: test-unit
63
- requirement: &70213347335220 !ruby/object:Gem::Requirement
60
+ requirement: &70207313926400 !ruby/object:Gem::Requirement
64
61
  none: false
65
62
  requirements:
66
- - - ~>
63
+ - - ! '>='
67
64
  - !ruby/object:Gem::Version
68
- version: '2.4'
65
+ version: '0'
69
66
  type: :development
70
67
  prerelease: false
71
- version_requirements: *70213347335220
68
+ version_requirements: *70207313926400
72
69
  - !ruby/object:Gem::Dependency
73
70
  name: webmock
74
- requirement: &70213347334540 !ruby/object:Gem::Requirement
71
+ requirement: &70207313936720 !ruby/object:Gem::Requirement
75
72
  none: false
76
73
  requirements:
77
- - - ~>
74
+ - - ! '>='
78
75
  - !ruby/object:Gem::Version
79
- version: '1.7'
76
+ version: '0'
80
77
  type: :development
81
78
  prerelease: false
82
- version_requirements: *70213347334540
79
+ version_requirements: *70207313936720
83
80
  description: HTTP/REST API client library.
84
81
  email: technoweenie@gmail.com
85
82
  executables: []
@@ -118,6 +115,7 @@ files:
118
115
  - test/adapters/logger_test.rb
119
116
  - test/adapters/net_http_test.rb
120
117
  - test/adapters/test_middleware_test.rb
118
+ - test/adapters/typhoeus_test.rb
121
119
  - test/connection_test.rb
122
120
  - test/env_test.rb
123
121
  - test/helper.rb
@@ -145,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
143
  version: 1.3.5
146
144
  requirements: []
147
145
  rubyforge_project: faraday
148
- rubygems_version: 1.8.10
146
+ rubygems_version: 1.8.12
149
147
  signing_key:
150
148
  specification_version: 2
151
149
  summary: HTTP/REST API client library.
@@ -154,6 +152,7 @@ test_files:
154
152
  - test/adapters/logger_test.rb
155
153
  - test/adapters/net_http_test.rb
156
154
  - test/adapters/test_middleware_test.rb
155
+ - test/adapters/typhoeus_test.rb
157
156
  - test/connection_test.rb
158
157
  - test/env_test.rb
159
158
  - test/helper.rb
@@ -161,3 +160,4 @@ test_files:
161
160
  - test/middleware_stack_test.rb
162
161
  - test/request_middleware_test.rb
163
162
  - test/response_middleware_test.rb
163
+ has_rdoc: