faraday 0.9.0.rc5 → 0.9.0.rc6

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.
Files changed (45) hide show
  1. data/Gemfile +6 -5
  2. data/README.md +0 -22
  3. data/faraday.gemspec +2 -2
  4. data/lib/faraday.rb +6 -2
  5. data/lib/faraday/adapter/em_http.rb +34 -14
  6. data/lib/faraday/adapter/em_http_ssl_patch.rb +56 -0
  7. data/lib/faraday/adapter/em_synchrony.rb +21 -20
  8. data/lib/faraday/adapter/excon.rb +16 -0
  9. data/lib/faraday/adapter/httpclient.rb +14 -0
  10. data/lib/faraday/adapter/net_http.rb +6 -2
  11. data/lib/faraday/adapter/net_http_persistent.rb +15 -3
  12. data/lib/faraday/adapter/patron.rb +13 -11
  13. data/lib/faraday/adapter/typhoeus.rb +11 -0
  14. data/lib/faraday/autoload.rb +2 -4
  15. data/lib/faraday/connection.rb +30 -3
  16. data/lib/faraday/error.rb +4 -1
  17. data/lib/faraday/options.rb +117 -23
  18. data/lib/faraday/request/instrumentation.rb +1 -3
  19. data/lib/faraday/request/multipart.rb +1 -1
  20. data/lib/faraday/request/retry.rb +38 -9
  21. data/lib/faraday/response.rb +1 -2
  22. data/lib/faraday/response/raise_error.rb +3 -0
  23. data/lib/faraday/utils.rb +10 -4
  24. data/script/proxy-server +42 -0
  25. data/script/server +1 -3
  26. data/script/test +35 -7
  27. data/test/adapters/excon_test.rb +4 -0
  28. data/test/adapters/httpclient_test.rb +5 -0
  29. data/test/adapters/integration.rb +48 -2
  30. data/test/adapters/net_http_persistent_test.rb +10 -1
  31. data/test/adapters/patron_test.rb +3 -0
  32. data/test/adapters/rack_test.rb +5 -0
  33. data/test/adapters/typhoeus_test.rb +3 -13
  34. data/test/authentication_middleware_test.rb +6 -6
  35. data/test/connection_test.rb +123 -49
  36. data/test/env_test.rb +19 -1
  37. data/test/helper.rb +2 -4
  38. data/test/live_server.rb +4 -2
  39. data/test/middleware/instrumentation_test.rb +13 -0
  40. data/test/middleware/retry_test.rb +47 -0
  41. data/test/multibyte.txt +1 -0
  42. data/test/options_test.rb +93 -17
  43. data/test/request_middleware_test.rb +6 -6
  44. data/test/utils_test.rb +34 -13
  45. metadata +69 -44
@@ -6,6 +6,9 @@ module Faraday
6
6
  case env[:status]
7
7
  when 404
8
8
  raise Faraday::Error::ResourceNotFound, response_values(env)
9
+ when 407
10
+ # mimic the behavior that we get with proxy requests with HTTPS
11
+ raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
9
12
  when ClientErrorStatuses
10
13
  raise Faraday::Error::ClientError, response_values(env)
11
14
  end
@@ -11,10 +11,10 @@ module Faraday
11
11
  new(value)
12
12
  end
13
13
 
14
- def initialize(hash={})
14
+ def initialize(hash = nil)
15
15
  super()
16
16
  @names = {}
17
- self.update hash
17
+ self.update(hash || {})
18
18
  end
19
19
 
20
20
  # need to synchronize concurrent writes to the shared KeyMap
@@ -45,6 +45,12 @@ module Faraday
45
45
  super k, v
46
46
  end
47
47
 
48
+ def fetch(k, *args, &block)
49
+ k = KeyMap[k]
50
+ key = @names.fetch(k.downcase, k)
51
+ super(key, *args, &block)
52
+ end
53
+
48
54
  def delete(k)
49
55
  k = KeyMap[k]
50
56
  if k = @names[k.downcase]
@@ -162,8 +168,8 @@ module Faraday
162
168
  ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
163
169
 
164
170
  def escape(s)
165
- s.to_s.gsub(ESCAPE_RE) {
166
- '%' + $&.unpack('H2' * $&.bytesize).join('%').upcase
171
+ s.to_s.gsub(ESCAPE_RE) {|match|
172
+ '%' + match.unpack('H2' * match.bytesize).join('%').upcase
167
173
  }.tr(' ', '+')
168
174
  end
169
175
 
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # Usage: script/proxy-server [-p PORT] [-u USER:PASSWORD]
3
+ require 'webrick'
4
+ require 'webrick/httpproxy'
5
+
6
+ port = 4001
7
+
8
+ if found = ARGV.index('-p')
9
+ port = ARGV[found + 1].to_i
10
+ end
11
+ if found = ARGV.index('-u')
12
+ username, password = ARGV[found + 1].split(':', 2)
13
+ end
14
+
15
+ match_credentials = lambda { |credentials|
16
+ got_username, got_password = credentials.to_s.unpack("m*")[0].split(":", 2)
17
+ got_username == username && got_password == password
18
+ }
19
+
20
+ log_io = $stdout
21
+ log_io.sync = true
22
+
23
+ webrick_opts = {
24
+ :Port => port, :Logger => WEBrick::Log::new(log_io),
25
+ :AccessLog => [[log_io, "[%{X-Faraday-Adapter}i] %m %U -> %s %b"]],
26
+ :ProxyAuthProc => lambda { |req, res|
27
+ if username
28
+ type, credentials = req.header['proxy-authorization'].first.to_s.split(/\s+/, 2)
29
+ unless "Basic" == type && match_credentials.call(credentials)
30
+ res['proxy-authenticate'] = %{Basic realm="testing"}
31
+ raise WEBrick::HTTPStatus::ProxyAuthenticationRequired
32
+ end
33
+ end
34
+ }
35
+ }
36
+
37
+ proxy = WEBrick::HTTPProxyServer.new(webrick_opts)
38
+
39
+ trap(:TERM) { proxy.shutdown }
40
+ trap(:INT) { proxy.shutdown }
41
+
42
+ proxy.start
@@ -6,15 +6,13 @@ ensure
6
6
  $VERBOSE = old_verbose
7
7
  end
8
8
  require 'webrick'
9
- require 'fileutils'
10
9
 
11
10
  port = 4000
12
11
  if found = ARGV.index('-p')
13
12
  port = ARGV[found + 1].to_i
14
13
  end
15
14
 
16
- FileUtils.mkdir_p('log')
17
- log_io = File.open('log/test.log', 'w')
15
+ log_io = $stdout
18
16
  log_io.sync = true
19
17
 
20
18
  webrick_opts = {
@@ -24,6 +24,7 @@ if [[ "$RUBYOPT" != *"bundler/setup"* ]]; then
24
24
  fi
25
25
 
26
26
  port=3999
27
+ proxy_port=3998
27
28
  scheme=http
28
29
 
29
30
  if [ "$SSL" = "yes" ]; then
@@ -47,12 +48,18 @@ filter_matching() {
47
48
 
48
49
  start_server() {
49
50
  mkdir -p log
50
- script/server -p $port >log/server.log 2>&1 &
51
+ script/server -p $port >log/test.log 2>&1 &
52
+ echo $!
53
+ }
54
+
55
+ start_proxy() {
56
+ mkdir -p log
57
+ script/proxy-server -p $proxy_port -u "faraday@test.local:there is cake" >log/proxy.log 2>&1 &
51
58
  echo $!
52
59
  }
53
60
 
54
61
  server_started() {
55
- lsof -i :$port >/dev/null
62
+ lsof -i :${1?} >/dev/null
56
63
  }
57
64
 
58
65
  timestamp() {
@@ -62,7 +69,7 @@ timestamp() {
62
69
  wait_for_server() {
63
70
  timeout=$(( `timestamp` + $1 ))
64
71
  while true; do
65
- if server_started; then
72
+ if server_started "$2"; then
66
73
  break
67
74
  elif [ `timestamp` -gt "$timeout" ]; then
68
75
  echo "timed out after $1 seconds" >&2
@@ -109,27 +116,47 @@ fi
109
116
 
110
117
  # If there are any adapter tests, spin up the HTTP server
111
118
  if [ -n "$(filter_matching "adapters" "${test_files[@]}")" ]; then
112
- if server_started; then
119
+ if server_started $port; then
113
120
  echo "aborted: another instance of server running on $port" >&2
114
121
  exit 1
115
122
  fi
116
123
  server_pid=$(start_server)
117
- wait_for_server 15 || {
118
- cat log/server.log
124
+ proxy_pid=$(start_proxy)
125
+ wait_for_server 30 $port || {
126
+ cat log/test.log
127
+ kill "$server_pid"
128
+ kill "$proxy_pid"
119
129
  exit 1
120
130
  }
131
+ wait_for_server 5 $proxy_port
121
132
  cleanup() {
122
133
  if [ $? -ne 0 ] && [ -n "$TRAVIS" ]; then
123
134
  cat log/test.log
124
135
  fi
125
136
  kill "$server_pid"
137
+ kill "$proxy_pid"
126
138
  }
127
139
  trap cleanup INT EXIT
128
140
  export LIVE="${scheme}://localhost:${port}"
141
+ export LIVE_PROXY="http://faraday%40test.local:there%20is%20cake@localhost:${proxy_port}"
129
142
  fi
130
143
 
144
+ warnings="${TMPDIR:-/tmp}/faraday-warnings.$$"
145
+
131
146
  run_test_files() {
132
- ruby -e 'while f=ARGV.shift and f!="--"; load f; end' "${test_files[@]}" -- "$@"
147
+ # Save warnings on stderr to a separate file
148
+ RUBYOPT="$RUBYOPT -w" ruby -e 'while f=ARGV.shift and f!="--"; load f; end' "${test_files[@]}" -- "$@" \
149
+ 2> >(tee >(grep 'warning:' >"$warnings") | grep -v 'warning:')
150
+ }
151
+
152
+ check_warnings() {
153
+ # Display Ruby warnings from this project's source files. Abort if any were found.
154
+ num="$(grep -F "$PWD" "$warnings" | grep -v "${PWD}/bundle" | sort | uniq -c | sort -rn | tee /dev/stderr | wc -l)"
155
+ rm -f "$warnings"
156
+ if [ "$num" -gt 0 ]; then
157
+ echo "FAILED: this test suite doesn't tolerate Ruby syntax warnings!" >&2
158
+ exit 1
159
+ fi
133
160
  }
134
161
 
135
162
  if [ -n "$RBENV_VERSIONS" ]; then
@@ -142,3 +169,4 @@ else
142
169
  run_test_files "$@"
143
170
  fi
144
171
 
172
+ check_warnings
@@ -8,6 +8,10 @@ module Adapters
8
8
  Integration.apply(self, :NonParallel) do
9
9
  # https://github.com/geemus/excon/issues/126 ?
10
10
  undef :test_timeout if ssl_mode?
11
+
12
+ # Excon lets OpenSSL::SSL::SSLError be raised without any way to
13
+ # distinguish whether it happened because of a 407 proxy response
14
+ undef :test_proxy_auth_fail if ssl_mode?
11
15
  end
12
16
  end
13
17
  end
@@ -6,6 +6,11 @@ module Adapters
6
6
  def adapter() :httpclient end
7
7
 
8
8
  Integration.apply(self, :NonParallel) do
9
+ def setup
10
+ require 'httpclient' unless defined?(HTTPClient)
11
+ HTTPClient::NO_PROXY_HOSTS.delete('localhost')
12
+ end
13
+
9
14
  def test_binds_local_socket
10
15
  host = '1.2.3.4'
11
16
  conn = create_connection :request => { :bind => { :host => host } }
@@ -12,6 +12,7 @@ module Adapters
12
12
  if base.live_server?
13
13
  features = [:Common]
14
14
  features.concat extra_features
15
+ features << :SSL if base.ssl_mode?
15
16
  features.each {|name| base.send(:include, self.const_get(name)) }
16
17
  yield if block_given?
17
18
  elsif !defined? @warned
@@ -58,7 +59,18 @@ module Adapters
58
59
  module Compression
59
60
  def test_GET_handles_compression
60
61
  res = get('echo_header', :name => 'accept-encoding')
61
- assert_match /gzip;.+\bdeflate\b/, res.body
62
+ assert_match(/gzip;.+\bdeflate\b/, res.body)
63
+ end
64
+ end
65
+
66
+ module SSL
67
+ def test_GET_ssl_fails_with_bad_cert
68
+ ca_file = 'tmp/faraday-different-ca-cert.crt'
69
+ conn = create_connection(:ssl => {:ca_file => ca_file})
70
+ err = assert_raises Faraday::SSLError do
71
+ conn.get('/ssl')
72
+ end
73
+ assert_includes err.message, "certificate"
62
74
  end
63
75
  end
64
76
 
@@ -118,7 +130,7 @@ module Adapters
118
130
  resp = post('file') do |req|
119
131
  req.body = {'uploaded_file' => Faraday::UploadIO.new(__FILE__, 'text/x-ruby')}
120
132
  end
121
- assert_equal "file integration.rb text/x-ruby", resp.body
133
+ assert_equal "file integration.rb text/x-ruby #{File.size(__FILE__)}", resp.body
122
134
  end
123
135
 
124
136
  def test_PUT_send_url_encoded_params
@@ -166,6 +178,40 @@ module Adapters
166
178
  end
167
179
  end
168
180
 
181
+ def test_connection_error
182
+ assert_raises Faraday::Error::ConnectionFailed do
183
+ get 'http://localhost:4'
184
+ end
185
+ end
186
+
187
+ def test_proxy
188
+ proxy_uri = URI(ENV['LIVE_PROXY'])
189
+ conn = create_connection(:proxy => proxy_uri)
190
+
191
+ res = conn.get '/echo'
192
+ assert_equal 'get', res.body
193
+
194
+ unless self.class.ssl_mode?
195
+ # proxy can't append "Via" header for HTTPS responses
196
+ assert_match(/:#{proxy_uri.port}$/, res['via'])
197
+ end
198
+ end
199
+
200
+ def test_proxy_auth_fail
201
+ proxy_uri = URI(ENV['LIVE_PROXY'])
202
+ proxy_uri.password = 'WRONG'
203
+ conn = create_connection(:proxy => proxy_uri)
204
+
205
+ err = assert_raises Faraday::Error::ConnectionFailed do
206
+ conn.get '/echo'
207
+ end
208
+
209
+ unless self.class.ssl_mode? && self.class.jruby?
210
+ # JRuby raises "End of file reached" which cannot be distinguished from a 407
211
+ assert_equal %{407 "Proxy Authentication Required "}, err.message
212
+ end
213
+ end
214
+
169
215
  def test_empty_body_response_represented_as_blank_string
170
216
  response = get('204')
171
217
  assert_equal '', response.body
@@ -5,7 +5,16 @@ module Adapters
5
5
 
6
6
  def adapter() :net_http_persistent end
7
7
 
8
- Integration.apply(self, :NonParallel)
8
+ Integration.apply(self, :NonParallel) do
9
+ def setup
10
+ if defined?(Net::HTTP::Persistent)
11
+ # work around problems with mixed SSL certificates
12
+ # https://github.com/drbrain/net-http-persistent/issues/45
13
+ http = Net::HTTP::Persistent.new('Faraday')
14
+ http.ssl_cleanup(4)
15
+ end
16
+ end if ssl_mode?
17
+ end
9
18
 
10
19
  end
11
20
  end
@@ -11,6 +11,9 @@ module Adapters
11
11
 
12
12
  # https://github.com/toland/patron/issues/52
13
13
  undef :test_GET_with_body
14
+
15
+ # no support for SSL peer verification
16
+ undef :test_GET_ssl_fails_with_bad_cert if ssl_mode?
14
17
  end unless jruby?
15
18
 
16
19
  end
@@ -22,5 +22,10 @@ module Adapters
22
22
  rescue Faraday::Error::ClientError
23
23
  end
24
24
  end
25
+
26
+ # test not applicable
27
+ undef test_connection_error
28
+ undef test_proxy
29
+ undef test_proxy_auth_fail
25
30
  end
26
31
  end
@@ -13,25 +13,15 @@ module Adapters
13
13
  # which libcurl seems to generate for this particular request:
14
14
  undef :test_POST_sends_files
15
15
 
16
+ # inconsistent outcomes ranging from successful response to connection error
17
+ undef :test_proxy_auth_fail if ssl_mode?
18
+
16
19
  def test_binds_local_socket
17
20
  host = '1.2.3.4'
18
21
  conn = create_connection :request => { :bind => { :host => host } }
19
22
  assert_equal host, conn.options[:bind][:host]
20
23
  end
21
24
 
22
- def test_GET_ssl_rejects_bad_hosts
23
- original_ssl_file = ENV['SSL_FILE']
24
- begin
25
- ENV['SSL_FILE'] = 'tmp/faraday-different-ca-cert.crt'
26
- conn = create_connection
27
- expected = ''
28
- response = conn.get('/ssl')
29
- assert_equal expected, response.body
30
- ensure
31
- ENV['SSL_FILE'] = original_ssl_file
32
- end
33
- end if ssl_mode?
34
-
35
25
  end unless jruby?
36
26
  end
37
27
  end
@@ -37,9 +37,9 @@ class AuthenticationMiddlewareTest < Faraday::TestCase
37
37
  response = conn { |b|
38
38
  b.request :token_auth, 'baz', :foo => 42
39
39
  }.get('/auth-echo')
40
- assert_match /^Token /, response.body
41
- assert_match /token="baz"/, response.body
42
- assert_match /foo="42"/, response.body
40
+ assert_match(/^Token /, response.body)
41
+ assert_match(/token="baz"/, response.body)
42
+ assert_match(/foo="42"/, response.body)
43
43
  end
44
44
 
45
45
  def test_token_middleware_does_not_interfere_with_existing_authorization
@@ -52,14 +52,14 @@ class AuthenticationMiddlewareTest < Faraday::TestCase
52
52
  response = conn { |b|
53
53
  b.request :authorization, 'custom', 'abc def'
54
54
  }.get('/auth-echo')
55
- assert_match /^custom abc def$/, response.body
55
+ assert_match(/^custom abc def$/, response.body)
56
56
  end
57
57
 
58
58
  def test_authorization_middleware_with_hash
59
59
  response = conn { |b|
60
60
  b.request :authorization, 'baz', :foo => 42
61
61
  }.get('/auth-echo')
62
- assert_match /^baz /, response.body
63
- assert_match /foo="42"/, response.body
62
+ assert_match(/^baz /, response.body)
63
+ assert_match(/foo="42"/, response.body)
64
64
  end
65
65
  end
@@ -2,10 +2,6 @@ require File.expand_path('../helper', __FILE__)
2
2
 
3
3
  class TestConnection < Faraday::TestCase
4
4
 
5
- def teardown
6
- Faraday::Utils.default_params_encoder = nil
7
- end
8
-
9
5
  def with_env(key, proxy)
10
6
  old_value = ENV.fetch(key, false)
11
7
  ENV[key] = proxy
@@ -101,109 +97,137 @@ class TestConnection < Faraday::TestCase
101
97
  assert_match(/nonce="abc"/, auth)
102
98
  end
103
99
 
104
- def test_build_url_uses_connection_host_as_default_uri_host
100
+ def test_build_exclusive_url_uses_connection_host_as_default_uri_host
105
101
  conn = Faraday::Connection.new
106
102
  conn.host = 'sushi.com'
107
103
  uri = conn.build_exclusive_url("/sake.html")
108
104
  assert_equal 'sushi.com', uri.host
109
105
  end
110
106
 
111
- def test_build_url_overrides_connection_port_for_absolute_urls
107
+ def test_build_exclusive_url_overrides_connection_port_for_absolute_urls
112
108
  conn = Faraday::Connection.new
113
109
  conn.port = 23
114
110
  uri = conn.build_exclusive_url("http://sushi.com")
115
111
  assert_equal 80, uri.port
116
112
  end
117
113
 
118
- def test_build_url_uses_connection_scheme_as_default_uri_scheme
114
+ def test_build_exclusive_url_uses_connection_scheme_as_default_uri_scheme
119
115
  conn = Faraday::Connection.new 'http://sushi.com'
120
116
  uri = conn.build_exclusive_url("/sake.html")
121
117
  assert_equal 'http', uri.scheme
122
118
  end
123
119
 
124
- def test_build_url_uses_connection_path_prefix_to_customize_path
120
+ def test_build_exclusive_url_uses_connection_path_prefix_to_customize_path
125
121
  conn = Faraday::Connection.new
126
122
  conn.path_prefix = '/fish'
127
123
  uri = conn.build_exclusive_url("sake.html")
128
124
  assert_equal '/fish/sake.html', uri.path
129
125
  end
130
126
 
131
- def test_build_url_uses_root_connection_path_prefix_to_customize_path
127
+ def test_build_exclusive_url_uses_root_connection_path_prefix_to_customize_path
132
128
  conn = Faraday::Connection.new
133
129
  conn.path_prefix = '/'
134
130
  uri = conn.build_exclusive_url("sake.html")
135
131
  assert_equal '/sake.html', uri.path
136
132
  end
137
133
 
138
- def test_build_url_forces_connection_path_prefix_to_be_absolute
134
+ def test_build_exclusive_url_forces_connection_path_prefix_to_be_absolute
139
135
  conn = Faraday::Connection.new
140
136
  conn.path_prefix = 'fish'
141
137
  uri = conn.build_exclusive_url("sake.html")
142
138
  assert_equal '/fish/sake.html', uri.path
143
139
  end
144
140
 
145
- def test_build_url_ignores_connection_path_prefix_trailing_slash
141
+ def test_build_exclusive_url_ignores_connection_path_prefix_trailing_slash
146
142
  conn = Faraday::Connection.new
147
143
  conn.path_prefix = '/fish/'
148
144
  uri = conn.build_exclusive_url("sake.html")
149
145
  assert_equal '/fish/sake.html', uri.path
150
146
  end
151
147
 
152
- def test_build_url_allows_absolute_uri_to_ignore_connection_path_prefix
148
+ def test_build_exclusive_url_allows_absolute_uri_to_ignore_connection_path_prefix
153
149
  conn = Faraday::Connection.new
154
150
  conn.path_prefix = '/fish'
155
151
  uri = conn.build_exclusive_url("/sake.html")
156
152
  assert_equal '/sake.html', uri.path
157
153
  end
158
154
 
159
- def test_build_url_parses_url_params_into_path
155
+ def test_build_exclusive_url_parses_url_params_into_path
160
156
  conn = Faraday::Connection.new
161
157
  uri = conn.build_exclusive_url("http://sushi.com/sake.html")
162
158
  assert_equal '/sake.html', uri.path
163
159
  end
164
160
 
165
- def test_build_url_doesnt_add_ending_slash_given_nil_url
161
+ def test_build_exclusive_url_doesnt_add_ending_slash_given_nil_url
166
162
  conn = Faraday::Connection.new
167
163
  conn.url_prefix = "http://sushi.com/nigiri"
168
164
  uri = conn.build_exclusive_url
169
165
  assert_equal "/nigiri", uri.path
170
166
  end
171
167
 
172
- def test_build_url_doesnt_add_ending_slash_given_empty_url
168
+ def test_build_exclusive_url_doesnt_add_ending_slash_given_empty_url
173
169
  conn = Faraday::Connection.new
174
170
  conn.url_prefix = "http://sushi.com/nigiri"
175
171
  uri = conn.build_exclusive_url('')
176
172
  assert_equal "/nigiri", uri.path
177
173
  end
178
-
179
- def test_build_url_parses_url_params_into_query
180
- uri = build_url("http://sushi.com/sake.html", 'a[b]' => '1 + 2')
174
+
175
+ def test_build_exclusive_url_doesnt_use_connection_params
176
+ conn = Faraday::Connection.new "http://sushi.com/nigiri"
177
+ conn.params = {:a => 1}
178
+ assert_equal "http://sushi.com/nigiri", conn.build_exclusive_url.to_s
179
+ end
180
+
181
+ def test_build_exclusive_url_uses_argument_params
182
+ conn = Faraday::Connection.new "http://sushi.com/nigiri"
183
+ conn.params = {:a => 1}
184
+ params = Faraday::Utils::ParamsHash.new
185
+ params[:a] = 2
186
+ url = conn.build_exclusive_url(nil, params)
187
+ assert_equal "http://sushi.com/nigiri?a=2", url.to_s
188
+ end
189
+
190
+ def test_build_url_uses_params
191
+ conn = Faraday::Connection.new "http://sushi.com/nigiri"
192
+ conn.params = {:a => 1, :b => 1}
193
+ assert_equal "http://sushi.com/nigiri?a=1&b=1", conn.build_url.to_s
194
+ end
195
+
196
+ def test_build_url_merges_params
197
+ conn = Faraday::Connection.new "http://sushi.com/nigiri"
198
+ conn.params = {:a => 1, :b => 1}
199
+ url = conn.build_url(nil, :b => 2, :c => 3)
200
+ assert_equal "http://sushi.com/nigiri?a=1&b=2&c=3", url.to_s
201
+ end
202
+
203
+ def test_env_url_parses_url_params_into_query
204
+ uri = env_url("http://sushi.com/sake.html", 'a[b]' => '1 + 2')
181
205
  assert_equal "a%5Bb%5D=1+%2B+2", uri.query
182
206
  end
183
207
 
184
- def test_build_url_escapes_per_spec
185
- uri = build_url('http:/', 'a' => '1+2 foo~bar.-baz')
208
+ def test_env_url_escapes_per_spec
209
+ uri = env_url('http:/', 'a' => '1+2 foo~bar.-baz')
186
210
  assert_equal "a=1%2B2+foo~bar.-baz", uri.query
187
211
  end
188
212
 
189
- def test_build_url_bracketizes_nested_params_in_query
190
- url = build_url nil, 'a' => {'b' => 'c'}
213
+ def test_env_url_bracketizes_nested_params_in_query
214
+ url = env_url nil, 'a' => {'b' => 'c'}
191
215
  assert_equal "a%5Bb%5D=c", url.query
192
216
  end
193
217
 
194
- def test_build_url_bracketizes_repeated_params_in_query
195
- uri = build_url("http://sushi.com/sake.html", 'a' => [1, 2])
218
+ def test_env_url_bracketizes_repeated_params_in_query
219
+ uri = env_url("http://sushi.com/sake.html", 'a' => [1, 2])
196
220
  assert_equal "a%5B%5D=1&a%5B%5D=2", uri.query
197
221
  end
198
222
 
199
- def test_build_url_without_braketizing_repeated_params_in_query
200
- uri = build_url 'http://sushi.com', 'a' => [1, 2] do |conn|
223
+ def test_env_url_without_braketizing_repeated_params_in_query
224
+ uri = env_url 'http://sushi.com', 'a' => [1, 2] do |conn|
201
225
  conn.options.params_encoder = Faraday::FlatParamsEncoder
202
226
  end
203
227
  assert_equal "a=1&a=2", uri.query
204
228
  end
205
229
 
206
- def test_build_url_parses_url
230
+ def test_build_exclusive_url_parses_url
207
231
  conn = Faraday::Connection.new
208
232
  uri = conn.build_exclusive_url("http://sushi.com/sake.html")
209
233
  assert_equal "http", uri.scheme
@@ -211,32 +235,32 @@ class TestConnection < Faraday::TestCase
211
235
  assert_equal '/sake.html', uri.path
212
236
  end
213
237
 
214
- def test_build_url_parses_url_and_changes_scheme
238
+ def test_build_exclusive_url_parses_url_and_changes_scheme
215
239
  conn = Faraday::Connection.new :url => "http://sushi.com/sushi"
216
240
  conn.scheme = 'https'
217
241
  uri = conn.build_exclusive_url("sake.html")
218
242
  assert_equal 'https://sushi.com/sushi/sake.html', uri.to_s
219
243
  end
220
244
 
221
- def test_build_url_joins_url_to_base_with_ending_slash
245
+ def test_build_exclusive_url_joins_url_to_base_with_ending_slash
222
246
  conn = Faraday::Connection.new :url => "http://sushi.com/sushi/"
223
247
  uri = conn.build_exclusive_url("sake.html")
224
248
  assert_equal 'http://sushi.com/sushi/sake.html', uri.to_s
225
249
  end
226
250
 
227
- def test_build_url_used_default_base_with_ending_slash
251
+ def test_build_exclusive_url_used_default_base_with_ending_slash
228
252
  conn = Faraday::Connection.new :url => "http://sushi.com/sushi/"
229
253
  uri = conn.build_exclusive_url
230
254
  assert_equal 'http://sushi.com/sushi/', uri.to_s
231
255
  end
232
256
 
233
- def test_build_url_overrides_base
257
+ def test_build_exclusive_url_overrides_base
234
258
  conn = Faraday::Connection.new :url => "http://sushi.com/sushi/"
235
259
  uri = conn.build_exclusive_url('/sake/')
236
260
  assert_equal 'http://sushi.com/sake/', uri.to_s
237
261
  end
238
262
 
239
- def test_build_url_handles_uri_instances
263
+ def test_build_exclusive_url_handles_uri_instances
240
264
  conn = Faraday::Connection.new
241
265
  uri = conn.build_exclusive_url(URI('/sake.html'))
242
266
  assert_equal '/sake.html', uri.path
@@ -291,6 +315,42 @@ class TestConnection < Faraday::TestCase
291
315
  end
292
316
  end
293
317
 
318
+ def test_proxy_accepts_env_without_scheme
319
+ with_env 'http_proxy', "localhost:8888" do
320
+ uri = Faraday::Connection.new.proxy[:uri]
321
+ assert_equal 'localhost', uri.host
322
+ assert_equal 8888, uri.port
323
+ end
324
+ end
325
+
326
+ def test_no_proxy_from_env
327
+ with_env 'http_proxy', nil do
328
+ conn = Faraday::Connection.new
329
+ assert_equal nil, conn.proxy
330
+ end
331
+ end
332
+
333
+ def test_no_proxy_from_blank_env
334
+ with_env 'http_proxy', '' do
335
+ conn = Faraday::Connection.new
336
+ assert_equal nil, conn.proxy
337
+ end
338
+ end
339
+
340
+ def test_proxy_doesnt_accept_uppercase_env
341
+ with_env 'HTTP_PROXY', "http://localhost:8888/" do
342
+ conn = Faraday::Connection.new
343
+ assert_nil conn.proxy
344
+ end
345
+ end
346
+
347
+ def test_proxy_requires_uri
348
+ conn = Faraday::Connection.new
349
+ assert_raises ArgumentError do
350
+ conn.proxy :uri => :bad_uri, :user => 'rick'
351
+ end
352
+ end
353
+
294
354
  def test_dups_connection_object
295
355
  conn = Faraday::Connection.new 'http://sushi.com/foo',
296
356
  :ssl => { :verify => :none },
@@ -333,7 +393,7 @@ class TestConnection < Faraday::TestCase
333
393
  assert_equal '/omnom', conn.path_prefix
334
394
  end
335
395
 
336
- def build_url(url, params)
396
+ def env_url(url, params)
337
397
  conn = Faraday::Connection.new(url, :params => params)
338
398
  yield conn if block_given?
339
399
  req = conn.build_request(:get)
@@ -356,6 +416,16 @@ class TestRequestParams < Faraday::TestCase
356
416
  assert_equal expected, query.split('&').sort
357
417
  end
358
418
 
419
+ def with_default_params_encoder(encoder)
420
+ old_encoder = Faraday::Utils.default_params_encoder
421
+ begin
422
+ Faraday::Utils.default_params_encoder = encoder
423
+ yield
424
+ ensure
425
+ Faraday::Utils.default_params_encoder = old_encoder
426
+ end
427
+ end
428
+
359
429
  def test_merges_connection_and_request_params
360
430
  create_connection 'http://a.co/?token=abc', :params => {'format' => 'json'}
361
431
  query = get '?page=1', :limit => 5
@@ -412,31 +482,35 @@ class TestRequestParams < Faraday::TestCase
412
482
  end
413
483
 
414
484
  def test_array_params_in_url
415
- Faraday::Utils.default_params_encoder = nil
416
- create_connection 'http://a.co/page1?color[]=red&color[]=blue'
417
- query = get
418
- assert_equal "color%5B%5D=red&color%5B%5D=blue", query
485
+ with_default_params_encoder(nil) do
486
+ create_connection 'http://a.co/page1?color[]=red&color[]=blue'
487
+ query = get
488
+ assert_equal "color%5B%5D=red&color%5B%5D=blue", query
489
+ end
419
490
  end
420
491
 
421
492
  def test_array_params_in_params
422
- Faraday::Utils.default_params_encoder = nil
423
- create_connection 'http://a.co/page1', :params => {:color => ['red', 'blue']}
424
- query = get
425
- assert_equal "color%5B%5D=red&color%5B%5D=blue", query
493
+ with_default_params_encoder(nil) do
494
+ create_connection 'http://a.co/page1', :params => {:color => ['red', 'blue']}
495
+ query = get
496
+ assert_equal "color%5B%5D=red&color%5B%5D=blue", query
497
+ end
426
498
  end
427
499
 
428
500
  def test_array_params_in_url_with_flat_params
429
- Faraday::Utils.default_params_encoder = Faraday::FlatParamsEncoder
430
- create_connection 'http://a.co/page1?color=red&color=blue'
431
- query = get
432
- assert_equal "color=red&color=blue", query
501
+ with_default_params_encoder(Faraday::FlatParamsEncoder) do
502
+ create_connection 'http://a.co/page1?color=red&color=blue'
503
+ query = get
504
+ assert_equal "color=red&color=blue", query
505
+ end
433
506
  end
434
507
 
435
508
  def test_array_params_in_params_with_flat_params
436
- Faraday::Utils.default_params_encoder = Faraday::FlatParamsEncoder
437
- create_connection 'http://a.co/page1', :params => {:color => ['red', 'blue']}
438
- query = get
439
- assert_equal "color=red&color=blue", query
509
+ with_default_params_encoder(Faraday::FlatParamsEncoder) do
510
+ create_connection 'http://a.co/page1', :params => {:color => ['red', 'blue']}
511
+ query = get
512
+ assert_equal "color=red&color=blue", query
513
+ end
440
514
  end
441
515
 
442
516
  def get(*args)