faraday 0.9.0.rc5 → 0.9.0.rc6

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