faraday 0.8.7 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,26 +1,20 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- group :development do
4
- gem 'sinatra', '~> 1.3'
5
- end
3
+ gem 'ffi-ncurses', '~> 0.3', :platforms => :jruby
4
+ gem 'jruby-openssl', '~> 0.8.8', :platforms => :jruby
5
+ gem 'rake'
6
6
 
7
7
  group :test do
8
- gem 'em-http-request', '~> 1.0', :require => 'em-http'
9
- gem 'em-synchrony', '~> 1.0', :require => ['em-synchrony', 'em-synchrony/em-http']
10
- gem 'excon', '>= 0.16.1'
11
- gem 'net-http-persistent', '~> 2.5', :require => false
12
- gem 'leftright', '~> 0.9', :require => false
13
- gem 'rack-test', '~> 0.6', :require => 'rack/test'
14
- end
15
-
16
- platforms :ruby do
17
- gem 'patron', '~> 0.4', '> 0.4.1'
18
- gem 'typhoeus', '~> 0.3.3'
19
- end
20
-
21
- platforms :jruby do
22
- gem 'jruby-openssl', '~> 0.7'
23
- gem 'ffi-ncurses', '~> 0.3'
8
+ gem 'em-http-request', '>= 1.1', :require => 'em-http'
9
+ gem 'em-synchrony', '>= 1.0', :require => ['em-synchrony', 'em-synchrony/em-http']
10
+ gem 'excon', '>= 0.25.3'
11
+ gem 'leftright', '>= 0.9', :require => false
12
+ gem 'net-http-persistent', '>= 2.5', :require => false
13
+ gem 'patron', '>= 0.4.2', :platforms => :ruby
14
+ gem 'rack-test', '>= 0.6', :require => 'rack/test'
15
+ gem 'simplecov'
16
+ gem 'sinatra', '~> 1.3'
17
+ gem 'typhoeus', '~> 0.3.3', :platforms => :ruby
24
18
  end
25
19
 
26
20
  gemspec
@@ -1,5 +1,5 @@
1
1
  module Faraday
2
- VERSION = "0.8.7"
2
+ VERSION = "0.8.8"
3
3
 
4
4
  class << self
5
5
  attr_accessor :root_path, :lib_path
@@ -7,7 +7,6 @@ module Faraday
7
7
  module Options
8
8
  def connection_config(env)
9
9
  options = {}
10
- configure_ssl(options, env)
11
10
  configure_proxy(options, env)
12
11
  configure_timeout(options, env)
13
12
  options
@@ -21,9 +20,6 @@ module Faraday
21
20
  # :file => 'path/to/file', # stream data off disk
22
21
  }
23
22
  configure_compression(options, env)
24
- # configure_proxy_auth
25
- # :proxy => {:authorization => [user, pass]}
26
- # proxy[:username] && proxy[:password]
27
23
  options
28
24
  end
29
25
 
@@ -32,20 +28,12 @@ module Faraday
32
28
  body.respond_to?(:read) ? body.read : body
33
29
  end
34
30
 
35
- def configure_ssl(options, env)
36
- if ssl = env[:ssl]
37
- # :ssl => {
38
- # :private_key_file => '/tmp/server.key',
39
- # :cert_chain_file => '/tmp/server.crt',
40
- # :verify_peer => false
41
- end
42
- end
43
-
44
31
  def configure_proxy(options, env)
45
32
  if proxy = request_options(env)[:proxy]
46
33
  options[:proxy] = {
47
34
  :host => proxy[:uri].host,
48
- :port => proxy[:uri].port
35
+ :port => proxy[:uri].port,
36
+ :authorization => [proxy[:user], proxy[:password]]
49
37
  }
50
38
  end
51
39
  end
@@ -114,6 +102,12 @@ module Faraday
114
102
  }
115
103
  end
116
104
  end
105
+ rescue EventMachine::Connectify::CONNECTError => err
106
+ if err.message.include?("Proxy Authentication Required")
107
+ raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
108
+ else
109
+ raise Error::ConnectionFailed, err
110
+ end
117
111
  end
118
112
 
119
113
  # TODO: reuse the connection to support pipelining
@@ -140,6 +134,8 @@ module Faraday
140
134
  elsif msg == Errno::ECONNREFUSED
141
135
  errklass = Faraday::Error::ConnectionFailed
142
136
  msg = "connection refused"
137
+ elsif msg == "connection closed by server"
138
+ errklass = Faraday::Error::ConnectionFailed
143
139
  end
144
140
  raise errklass, msg
145
141
  end
@@ -52,6 +52,8 @@ module Faraday
52
52
  client = block.call
53
53
  end
54
54
 
55
+ raise client.error if client.error
56
+
55
57
  save_response(env, client.response_header.status, client.response) do |resp_headers|
56
58
  client.response_header.each do |name, value|
57
59
  resp_headers[name.to_sym] = value
@@ -62,6 +64,12 @@ module Faraday
62
64
  @app.call env
63
65
  rescue Errno::ECONNREFUSED
64
66
  raise Error::ConnectionFailed, $!
67
+ rescue EventMachine::Connectify::CONNECTError => err
68
+ if err.message.include?("Proxy Authentication Required")
69
+ raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
70
+ else
71
+ raise Error::ConnectionFailed, err
72
+ end
65
73
  end
66
74
  end
67
75
  end
@@ -28,6 +28,16 @@ module Faraday
28
28
  opts[:connect_timeout] = req[:open_timeout]
29
29
  opts[:write_timeout] = req[:open_timeout]
30
30
  end
31
+
32
+ if req[:proxy]
33
+ opts[:proxy] = {
34
+ :host => req[:proxy][:uri].host,
35
+ :port => req[:proxy][:uri].port,
36
+ :scheme => req[:proxy][:uri].scheme,
37
+ :user => req[:proxy][:user],
38
+ :password => req[:proxy][:password]
39
+ }
40
+ end
31
41
  end
32
42
 
33
43
  conn = ::Excon.new(env[:url].to_s, opts)
@@ -1,4 +1,6 @@
1
- require 'faraday/adapter/net_http'
1
+ # Rely on autoloading instead of explicit require; helps avoid the "already
2
+ # initialized constant" warning on Ruby 1.8.7 when NetHttp is refereced below.
3
+ # require 'faraday/adapter/net_http'
2
4
 
3
5
  module Faraday
4
6
  class Adapter
@@ -6,18 +8,26 @@ module Faraday
6
8
  class NetHttpPersistent < NetHttp
7
9
  dependency 'net/http/persistent'
8
10
 
9
- # TODO: investigate is it safe to create a new Persistent instance for
10
- # every request, or does it defy the purpose of persistent connections
11
11
  def net_http_connection(env)
12
- Net::HTTP::Persistent.new 'Faraday',
13
- env[:request][:proxy] ? env[:request][:proxy][:uri] : nil
12
+ if proxy = env[:request][:proxy]
13
+ proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
14
+ proxy_uri.user = proxy_uri.password = nil
15
+ # awful patch for net-http-persistent 2.8 not unescaping user/password
16
+ (class << proxy_uri; self; end).class_eval do
17
+ define_method(:user) { proxy[:user] }
18
+ define_method(:password) { proxy[:password] }
19
+ end if proxy[:user]
20
+ end
21
+ Net::HTTP::Persistent.new 'Faraday', proxy_uri
14
22
  end
15
23
 
16
24
  def perform_request(http, env)
17
25
  http.request env[:url], create_request(env)
18
26
  rescue Net::HTTP::Persistent::Error => error
19
- if error.message.include? 'Timeout::Error'
27
+ if error.message.include? 'Timeout'
20
28
  raise Faraday::Error::TimeoutError, error
29
+ elsif error.message.include? 'connection refused'
30
+ raise Faraday::Error::ConnectionFailed, error
21
31
  else
22
32
  raise
23
33
  end
@@ -5,7 +5,7 @@ module Faraday
5
5
 
6
6
  def initialize(app, &block)
7
7
  super(app)
8
- @block = block if block_given?
8
+ @block = block
9
9
  end
10
10
 
11
11
  def call(env)
@@ -19,19 +19,19 @@ module Faraday
19
19
  if req = env[:request]
20
20
  session.timeout = session.connect_timeout = req[:timeout] if req[:timeout]
21
21
  session.connect_timeout = req[:open_timeout] if req[:open_timeout]
22
-
22
+
23
23
  if proxy = req[:proxy]
24
- session.proxy = proxy[:uri].to_s
25
- if proxy[:user] && proxy[:password]
26
- prepend_proxy_auth_string(proxy, session)
27
- end
24
+ proxy_uri = proxy[:uri].dup
25
+ proxy_uri.user = proxy[:user] && Utils.escape(proxy[:user]).gsub('+', '%20')
26
+ proxy_uri.password = proxy[:password] && Utils.escape(proxy[:password]).gsub('+', '%20')
27
+ session.proxy = proxy_uri.to_s
28
28
  end
29
29
  end
30
30
 
31
31
  response = begin
32
32
  data = env[:body] ? env[:body].to_s : nil
33
33
  session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data)
34
- rescue Errno::ECONNREFUSED
34
+ rescue Errno::ECONNREFUSED, ::Patron::ConnectionFailed
35
35
  raise Error::ConnectionFailed, $!
36
36
  end
37
37
 
@@ -40,6 +40,12 @@ module Faraday
40
40
  @app.call env
41
41
  rescue ::Patron::TimeoutError => err
42
42
  raise Faraday::Error::TimeoutError, err
43
+ rescue ::Patron::Error => err
44
+ if err.message.include?("code 407")
45
+ raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
46
+ else
47
+ raise Error::ConnectionFailed, err
48
+ end
43
49
  end
44
50
 
45
51
  if loaded? && defined?(::Patron::Request::VALID_ACTIONS)
@@ -58,9 +64,5 @@ module Faraday
58
64
  session
59
65
  end
60
66
  end
61
-
62
- def prepend_proxy_auth_string(proxy, session)
63
- session.proxy.insert(7, "#{proxy[:user]}:#{proxy[:password]}@")
64
- end
65
67
  end
66
68
  end
@@ -31,8 +31,13 @@ module Faraday
31
31
  end
32
32
 
33
33
  def request(env)
34
+ method = env[:method]
35
+ # For some reason, prevents Typhoeus from using "100-continue".
36
+ # We want this because Webrick 1.3.1 can't seem to handle it w/ PUT.
37
+ method = method.to_s.upcase if method == :put
38
+
34
39
  req = ::Typhoeus::Request.new env[:url].to_s,
35
- :method => env[:method],
40
+ :method => method,
36
41
  :body => env[:body],
37
42
  :headers => env[:request_headers],
38
43
  :disable_ssl_peer_verification => (env[:ssl] && !env[:ssl].fetch(:verify, true))
@@ -50,6 +55,15 @@ module Faraday
50
55
  end
51
56
  end
52
57
 
58
+ case resp.curl_return_code
59
+ when 0
60
+ # everything OK
61
+ when 7
62
+ raise Error::ConnectionFailed, resp.curl_error_message
63
+ else
64
+ raise Error::ClientError, resp.curl_error_message
65
+ end
66
+
53
67
  save_response(env, resp.code, resp.body) do |response_headers|
54
68
  response_headers.parse resp.headers
55
69
  end
@@ -76,8 +90,8 @@ module Faraday
76
90
 
77
91
  req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}"
78
92
 
79
- if proxy[:username] && proxy[:password]
80
- req.proxy_username = proxy[:username]
93
+ if proxy[:user] && proxy[:password]
94
+ req.proxy_username = proxy[:user]
81
95
  req.proxy_password = proxy[:password]
82
96
  end
83
97
  end
@@ -54,7 +54,13 @@ module Faraday
54
54
  @headers.update options[:headers] if options[:headers]
55
55
 
56
56
  @proxy = nil
57
- proxy(options.fetch(:proxy) { ENV['http_proxy'] })
57
+ proxy(options.fetch(:proxy) {
58
+ uri = ENV['http_proxy']
59
+ if uri && !uri.empty?
60
+ uri = 'http://' + uri if uri !~ /^http/i
61
+ uri
62
+ end
63
+ })
58
64
 
59
65
  yield self if block_given?
60
66
 
@@ -7,7 +7,7 @@ module Faraday
7
7
  match_content_type(env) do |params|
8
8
  env[:request] ||= {}
9
9
  env[:request][:boundary] ||= DEFAULT_BOUNDARY
10
- env[:request_headers][CONTENT_TYPE] += ";boundary=#{env[:request][:boundary]}"
10
+ env[:request_headers][CONTENT_TYPE] += "; boundary=#{env[:request][:boundary]}"
11
11
  env[:body] = create_multipart(env, params)
12
12
  end
13
13
  @app.call env
@@ -4,6 +4,9 @@ module Faraday
4
4
  case env[:status]
5
5
  when 404
6
6
  raise Faraday::Error::ResourceNotFound, response_values(env)
7
+ when 407
8
+ # mimic the behavior that we get with proxy requests with HTTPS
9
+ raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
7
10
  when 400...600
8
11
  raise Faraday::Error::ClientError, response_values(env)
9
12
  end
@@ -173,8 +173,8 @@ module Faraday
173
173
  ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/
174
174
 
175
175
  def escape(s)
176
- s.to_s.gsub(ESCAPE_RE) {
177
- '%' + $&.unpack('H2' * $&.bytesize).join('%').upcase
176
+ s.to_s.gsub(ESCAPE_RE) {|match|
177
+ '%' + match.unpack('H2' * match.bytesize).join('%').upcase
178
178
  }.tr(' ', '+')
179
179
  end
180
180
 
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # Usage: generate_certs
3
+ # Generate test certs for testing Faraday with SSL
4
+
5
+ require 'openssl'
6
+ require 'fileutils'
7
+
8
+ $shell = ARGV.include? '-s'
9
+
10
+ # Adapted from WEBrick::Utils. Skips cert extensions so it
11
+ # can be used as a CA bundle
12
+ def create_self_signed_cert(bits, cn, comment)
13
+ rsa = OpenSSL::PKey::RSA.new(bits)
14
+ cert = OpenSSL::X509::Certificate.new
15
+ cert.version = 2
16
+ cert.serial = 1
17
+ name = OpenSSL::X509::Name.new(cn)
18
+ cert.subject = name
19
+ cert.issuer = name
20
+ cert.not_before = Time.now
21
+ cert.not_after = Time.now + (365*24*60*60)
22
+ cert.public_key = rsa.public_key
23
+ cert.sign(rsa, OpenSSL::Digest::SHA1.new)
24
+ return [cert, rsa]
25
+ end
26
+
27
+ def write(file, contents, env_var)
28
+ FileUtils.mkdir_p(File.dirname(file))
29
+ File.open(file, 'w') {|f| f.puts(contents) }
30
+ puts %(export #{env_var}="#{file}") if $shell
31
+ end
32
+
33
+
34
+ # One cert / CA for ease of testing when ignoring verification
35
+ cert, key = create_self_signed_cert(1024, [['CN', 'localhost']], 'Faraday Test CA')
36
+ write 'tmp/faraday-cert.key', key, 'SSL_KEY'
37
+ write 'tmp/faraday-cert.crt', cert, 'SSL_FILE'
38
+
39
+ # And a second CA to prove that verification can fail
40
+ cert, key = create_self_signed_cert(1024, [['CN', 'real-ca.com']], 'A different CA')
41
+ write 'tmp/faraday-different-ca-cert.key', key, 'SSL_KEY_ALT'
42
+ write 'tmp/faraday-different-ca-cert.crt', cert, 'SSL_FILE_ALT'
@@ -0,0 +1,41 @@
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
+ raise WEBrick::HTTPStatus::ProxyAuthenticationRequired
31
+ end
32
+ end
33
+ }
34
+ }
35
+
36
+ proxy = WEBrick::HTTPProxyServer.new(webrick_opts)
37
+
38
+ trap(:TERM) { proxy.shutdown }
39
+ trap(:INT) { proxy.shutdown }
40
+
41
+ proxy.start
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ old_verbose, $VERBOSE = $VERBOSE, nil
3
+ begin
4
+ require File.expand_path('../../test/live_server', __FILE__)
5
+ ensure
6
+ $VERBOSE = old_verbose
7
+ end
8
+ require 'webrick'
9
+
10
+ port = 4000
11
+ if found = ARGV.index('-p')
12
+ port = ARGV[found + 1].to_i
13
+ end
14
+
15
+ log_io = $stdout
16
+ log_io.sync = true
17
+
18
+ webrick_opts = {
19
+ :Port => port, :Logger => WEBrick::Log::new(log_io),
20
+ :AccessLog => [[log_io, "[%{X-Faraday-Adapter}i] %m %U -> %s %b"]]
21
+ }
22
+
23
+ if ENV['SSL_KEY']
24
+ require 'openssl'
25
+ require 'webrick/https'
26
+ webrick_opts.update \
27
+ :SSLEnable => true,
28
+ :SSLPrivateKey => OpenSSL::PKey::RSA.new(File.read(ENV['SSL_KEY'])),
29
+ :SSLCertificate => OpenSSL::X509::Certificate.new(File.read(ENV['SSL_FILE'])),
30
+ :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE
31
+ end
32
+
33
+ Rack::Handler::WEBrick.run(Faraday::LiveServer, webrick_opts) do |server|
34
+ trap(:INT) { server.stop }
35
+ trap(:TERM) { server.stop }
36
+ end
@@ -1,131 +1,170 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env bash
2
+ # Usage: script/test [file] [adapter]... -- [test/unit options]
2
3
  # Runs the test suite against a local server spawned automatically in a
3
4
  # thread. After tests are done, the server is shut down.
4
5
  #
5
6
  # If filename arguments are given, only those files are run. If arguments given
6
7
  # are not filenames, they are taken as words that filter the list of files to run.
7
8
  #
8
- # Examples
9
+ # Examples:
9
10
  #
10
11
  # $ script/test
11
12
  # $ script/test test/env_test.rb
12
13
  # $ script/test excon typhoeus
14
+ #
15
+ # # Run only tests matching /ssl/ for the net_http adapter, with SSL enabled.
13
16
  # $ SSL=yes script/test net_http -- -n /ssl/
17
+ #
18
+ # # Run against multiple rbenv versions
19
+ # $ RBENV_VERSIONS="1.9.3-p194 ree-1.8.7-2012.02" script/test
20
+ set -e
21
+
22
+ if [[ "$RUBYOPT" != *"bundler/setup"* ]]; then
23
+ export RUBYOPT="-rbundler/setup $RUBYOPT"
24
+ fi
25
+
26
+ port=3999
27
+ proxy_port=3998
28
+ scheme=http
29
+
30
+ if [ "$SSL" = "yes" ]; then
31
+ scheme=https
32
+ if [ -z "$SSL_KEY" ] || [ -z "$SSL_FILE" ]; then
33
+ eval "$(script/generate_certs -s)"
34
+ fi
35
+ fi
36
+
37
+ find_test_files() {
38
+ find "$1" -name '*_test.rb'
39
+ }
14
40
 
15
- require 'rubygems'
16
- require 'bundler'
17
- begin
18
- Bundler.setup
19
- rescue Bundler::GemNotFound
20
- $stderr.print "Error: "
21
- $stderr.puts $!.message
22
- warn "Run `bundle install` to install missing gems."
23
- exit 1
24
- end
25
-
26
- $VERBOSE = true
27
-
28
- host = 'localhost'
29
- logfile = 'log/test.log'
30
- test_glob = 'test/**/*_test.rb'
31
-
32
- if ssl_mode = ENV['SSL'] == 'yes'
33
- unless ENV['SSL_KEY'] and ENV['SSL_FILE']
34
- key_file = ENV['SSL_KEY'] = 'tmp/faraday-cert.key'
35
- cert_file = ENV['SSL_FILE'] = 'tmp/faraday-cert.crt'
36
- system 'rake', key_file, cert_file
37
- abort unless $?.success?
38
- end
39
- end
40
-
41
- require 'fileutils'
42
- FileUtils.mkdir_p 'log'
43
-
44
- # find available port
45
- require 'socket'
46
- port = begin
47
- server = TCPServer.new(host, 0)
48
- server.addr[1]
49
- ensure
50
- server.close if server
51
- end
52
-
53
- server = nil
54
-
55
- Thread.abort_on_exception = true
56
-
57
- # start test server in a separate thread
58
- thread = Thread.new do
59
- old_verbose, $VERBOSE = $VERBOSE, nil
60
- begin
61
- require File.expand_path('../../test/live_server', __FILE__)
62
- ensure
63
- $VERBOSE = old_verbose
64
- end
65
- require 'webrick'
66
- log_io = File.open logfile, 'w'
67
- log_io.sync = true
68
- webrick_opts = {
69
- :Port => port, :Logger => WEBrick::Log::new(log_io),
70
- :AccessLog => [[log_io, "[%{X-Faraday-Adapter}i] %m %U -> %s %b"]]
71
- }
72
- if ssl_mode
73
- require 'webrick/https'
74
- webrick_opts.update \
75
- :SSLEnable => true,
76
- :SSLPrivateKey => OpenSSL::PKey::RSA.new(File.read(key_file)),
77
- :SSLCertificate => OpenSSL::X509::Certificate.new(File.read(cert_file)),
78
- :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE
79
- end
80
- Rack::Handler::WEBrick.run(Faraday::LiveServer, webrick_opts) {|serv| server = serv }
81
- end
82
-
83
- # find files to test
84
- test_files = Dir[test_glob]
85
- if ARGV.any?
86
- all_files, test_files = test_files, []
87
- args, extra_args = ARGV, []
88
- if idx = args.index('--')
89
- extra_args = args[(idx+1)..-1]
90
- args = args[0, idx]
91
- end
92
- for arg in args
93
- re = /(\b|_)#{arg}(\b|_)/
94
- test_files.concat all_files.select { |f| f =~ re }
95
- end
96
- test_files.concat extra_args
97
- end
98
-
99
- require 'net/https'
100
- conn = Net::HTTP.new host, port
101
- conn.open_timeout = conn.read_timeout = 0.1
102
- conn.use_ssl = ssl_mode
103
- conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
104
-
105
- # test if test server is accepting requests
106
- responsive = lambda { |path|
107
- begin
108
- res = conn.start { conn.get(path) }
109
- res.is_a?(Net::HTTPSuccess)
110
- rescue Errno::ECONNREFUSED, Errno::EBADF, Timeout::Error, Net::HTTPBadResponse
111
- false
112
- end
41
+ filter_matching() {
42
+ pattern="$1"
43
+ shift
44
+ for line in "$@"; do
45
+ [[ $line == *"$pattern"* ]] && echo "$line"
46
+ done
47
+ }
48
+
49
+ start_server() {
50
+ mkdir -p log
51
+ script/server -p $port >log/test.log 2>&1 &
52
+ echo $!
113
53
  }
114
54
 
115
- server_pings = 0
116
- begin
117
- # block until test server is ready
118
- thread.join 0.05
119
- server_pings += 1
120
- abort "test server didn't manage to start" if server_pings >= 50
121
- end until responsive.call('/echo')
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 &
58
+ echo $!
59
+ }
122
60
 
123
- ENV['LIVE'] = "http#{ssl_mode ? 's' : ''}://#{host}:#{port}"
124
- ok = system 'ruby', '-Ilib:test',
125
- '-e', 'load(ARGV.shift) while ARGV.first =~ /^[^-]/',
126
- *test_files
61
+ server_started() {
62
+ lsof -i :${1?} >/dev/null
63
+ }
64
+
65
+ timestamp() {
66
+ date +%s
67
+ }
127
68
 
128
- server.respond_to?(:stop!) ? server.stop! : server.stop
129
- thread.join
69
+ wait_for_server() {
70
+ timeout=$(( `timestamp` + $1 ))
71
+ while true; do
72
+ if server_started "$2"; then
73
+ break
74
+ elif [ `timestamp` -gt "$timeout" ]; then
75
+ echo "timed out after $1 seconds" >&2
76
+ return 1
77
+ fi
78
+ done
79
+ }
80
+
81
+ filtered=
82
+ IFS=$'\n' test_files=($(find_test_files "test"))
83
+ declare -a explicit_files
84
+
85
+ # Process filter arguments:
86
+ # - test filenames as taken as-is
87
+ # - other words are taken as pattern to match the list of known files against
88
+ # - arguments after "--" are forwarded to the ruby process
89
+ while [ $# -gt 0 ]; do
90
+ arg="$1"
91
+ shift
92
+ if [ "$arg" = "--" ]; then
93
+ break
94
+ elif [ -f "$arg" ]; then
95
+ filtered=true
96
+ explicit_files[${#explicit_files[@]}+1]="$arg"
97
+ else
98
+ filtered=true
99
+ IFS=$'\n' explicit_files=(
100
+ ${explicit_files[@]}
101
+ $(filter_matching "$arg" "${test_files[@]}" || true)
102
+ )
103
+ fi
104
+ done
105
+
106
+ # If there were filter args, replace test files list with the results
107
+ if [ -n "$filtered" ]; then
108
+ if [ ${#explicit_files[@]} -eq 0 ]; then
109
+ echo "Error: no test files match" >&2
110
+ exit 1
111
+ else
112
+ test_files=(${explicit_files[@]})
113
+ echo running "${test_files[@]}"
114
+ fi
115
+ fi
116
+
117
+ # If there are any adapter tests, spin up the HTTP server
118
+ if [ -n "$(filter_matching "adapters" "${test_files[@]}")" ]; then
119
+ if server_started $port; then
120
+ echo "aborted: another instance of server running on $port" >&2
121
+ exit 1
122
+ fi
123
+ server_pid=$(start_server)
124
+ proxy_pid=$(start_proxy)
125
+ wait_for_server 15 $port || {
126
+ cat log/test.log
127
+ exit 1
128
+ }
129
+ wait_for_server 5 $proxy_port
130
+ cleanup() {
131
+ if [ $? -ne 0 ] && [ -n "$TRAVIS" ]; then
132
+ cat log/test.log
133
+ fi
134
+ kill "$server_pid"
135
+ kill "$proxy_pid"
136
+ }
137
+ trap cleanup INT EXIT
138
+ export LIVE="${scheme}://localhost:${port}"
139
+ export LIVE_PROXY="http://faraday%40test.local:there%20is%20cake@localhost:${proxy_port}"
140
+ fi
141
+
142
+ warnings="${TMPDIR:-/tmp}/faraday-warnings.$$"
143
+
144
+ run_test_files() {
145
+ # Save warnings on stderr to a separate file
146
+ RUBYOPT="$RUBYOPT -w" ruby -e 'while f=ARGV.shift and f!="--"; load f; end' "${test_files[@]}" -- "$@" \
147
+ 2> >(tee >(grep 'warning:' >"$warnings") | grep -v 'warning:')
148
+ }
149
+
150
+ check_warnings() {
151
+ # Display Ruby warnings from this project's source files. Abort if any were found.
152
+ num="$(grep -F "$PWD" "$warnings" | grep -v "${PWD}/bundle" | sort | uniq -c | sort -rn | tee /dev/stderr | wc -l)"
153
+ rm -f "$warnings"
154
+ if [ "$num" -gt 0 ]; then
155
+ echo "FAILED: this test suite doesn't tolerate Ruby syntax warnings!" >&2
156
+ exit 1
157
+ fi
158
+ }
130
159
 
131
- exit 1 unless ok
160
+ if [ -n "$RBENV_VERSIONS" ]; then
161
+ IFS=' ' versions=($RBENV_VERSIONS)
162
+ for version in "${versions[@]}"; do
163
+ echo "[${version}]"
164
+ RBENV_VERSION="$version" run_test_files "$@"
165
+ done
166
+ else
167
+ run_test_files "$@"
168
+ fi
169
+
170
+ 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
@@ -57,7 +57,7 @@ module Adapters
57
57
  module Compression
58
58
  def test_GET_handles_compression
59
59
  res = get('echo_header', :name => 'accept-encoding')
60
- assert_match /gzip;.+\bdeflate\b/, res.body
60
+ assert_match(/gzip;.+\bdeflate\b/, res.body)
61
61
  end
62
62
  end
63
63
 
@@ -117,7 +117,7 @@ module Adapters
117
117
  resp = post('file') do |req|
118
118
  req.body = {'uploaded_file' => Faraday::UploadIO.new(__FILE__, 'text/x-ruby')}
119
119
  end
120
- assert_equal "file integration.rb text/x-ruby", resp.body
120
+ assert_equal "file integration.rb text/x-ruby #{File.size(__FILE__)}", resp.body
121
121
  end
122
122
 
123
123
  def test_PUT_send_url_encoded_params
@@ -166,6 +166,40 @@ module Adapters
166
166
  end
167
167
  end
168
168
 
169
+ def test_connection_error
170
+ assert_raise Faraday::Error::ConnectionFailed do
171
+ get 'http://localhost:4'
172
+ end
173
+ end
174
+
175
+ def test_proxy
176
+ proxy_uri = URI(ENV['LIVE_PROXY'])
177
+ conn = create_connection(:proxy => proxy_uri)
178
+
179
+ res = conn.get '/echo'
180
+ assert_equal 'get', res.body
181
+
182
+ unless self.class.ssl_mode?
183
+ # proxy can't append "Via" header for HTTPS responses
184
+ assert_match(/:#{proxy_uri.port}$/, res['via'])
185
+ end
186
+ end
187
+
188
+ def test_proxy_auth_fail
189
+ proxy_uri = URI(ENV['LIVE_PROXY'])
190
+ proxy_uri.password = 'WRONG'
191
+ conn = create_connection(:proxy => proxy_uri)
192
+
193
+ err = assert_raise Faraday::Error::ConnectionFailed do
194
+ conn.get '/echo'
195
+ end
196
+
197
+ unless self.class.ssl_mode? && self.class.jruby?
198
+ # JRuby raises "End of file reached" which cannot be distinguished from a 407
199
+ assert_equal %{407 "Proxy Authentication Required "}, err.message
200
+ end
201
+ end
202
+
169
203
  def adapter
170
204
  raise NotImplementedError.new("Need to override #adapter")
171
205
  end
@@ -5,10 +5,7 @@ module Adapters
5
5
 
6
6
  def adapter() :net_http_persistent end
7
7
 
8
- Integration.apply(self, :NonParallel) do
9
- # https://github.com/drbrain/net-http-persistent/issues/33
10
- undef :test_timeout
11
- end
8
+ Integration.apply(self, :NonParallel)
12
9
 
13
10
  end
14
11
  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
@@ -8,6 +8,13 @@ module Adapters
8
8
  Integration.apply(self, :Parallel) do
9
9
  # https://github.com/dbalatero/typhoeus/issues/75
10
10
  undef :test_GET_with_body
11
+
12
+ # Not a Typhoeus bug, but WEBrick inability to handle "100-continue"
13
+ # which libcurl seems to generate for this particular request:
14
+ undef :test_POST_sends_files
15
+
16
+ # inconsistent outcomes ranging from successful response to connection error
17
+ undef :test_proxy_auth_fail if ssl_mode?
11
18
  end unless jruby?
12
19
 
13
20
  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
@@ -93,9 +93,9 @@ class TestConnection < Faraday::TestCase
93
93
 
94
94
  conn.token_auth 'abcdef', :nonce => 'abc'
95
95
  assert auth = conn.headers['Authorization']
96
- assert_match /^Token /, auth
97
- assert_match /token="abcdef"/, auth
98
- assert_match /nonce="abc"/, auth
96
+ assert_match(/^Token /, auth)
97
+ assert_match(/token="abcdef"/, auth)
98
+ assert_match(/nonce="abc"/, auth)
99
99
  end
100
100
 
101
101
  def test_build_url_uses_connection_host_as_default_uri_host
@@ -263,6 +263,35 @@ class TestConnection < Faraday::TestCase
263
263
  end
264
264
  end
265
265
 
266
+ def test_proxy_accepts_env_without_scheme
267
+ with_env 'http_proxy', "localhost:8888" do
268
+ uri = Faraday::Connection.new.proxy[:uri]
269
+ assert_equal 'localhost', uri.host
270
+ assert_equal 8888, uri.port
271
+ end
272
+ end
273
+
274
+ def test_no_proxy_from_env
275
+ with_env 'http_proxy', nil do
276
+ conn = Faraday::Connection.new
277
+ assert_equal nil, conn.proxy
278
+ end
279
+ end
280
+
281
+ def test_no_proxy_from_blank_env
282
+ with_env 'http_proxy', '' do
283
+ conn = Faraday::Connection.new
284
+ assert_equal nil, conn.proxy
285
+ end
286
+ end
287
+
288
+ def test_proxy_doesnt_accept_uppercase_env
289
+ with_env 'HTTP_PROXY', "http://localhost:8888/" do
290
+ conn = Faraday::Connection.new
291
+ assert_nil conn.proxy
292
+ end
293
+ end
294
+
266
295
  def test_proxy_requires_uri
267
296
  conn = Faraday::Connection.new
268
297
  assert_raises ArgumentError do
@@ -3,6 +3,7 @@ unless ENV['CI']
3
3
  require 'simplecov'
4
4
  SimpleCov.start do
5
5
  add_filter 'test'
6
+ add_filter '/bundle/'
6
7
  end
7
8
  rescue LoadError
8
9
  end
@@ -20,14 +21,6 @@ end
20
21
 
21
22
  require File.expand_path('../../lib/faraday', __FILE__)
22
23
 
23
- begin
24
- require 'ruby-debug'
25
- rescue LoadError
26
- # ignore
27
- else
28
- Debugger.start
29
- end
30
-
31
24
  require 'stringio'
32
25
  require 'uri'
33
26
 
@@ -25,9 +25,11 @@ class LiveServer < Sinatra::Base
25
25
 
26
26
  post '/file' do
27
27
  if params[:uploaded_file].respond_to? :each_key
28
- "file %s %s" % [
28
+ "file %s %s %d" % [
29
29
  params[:uploaded_file][:filename],
30
- params[:uploaded_file][:type]]
30
+ params[:uploaded_file][:type],
31
+ params[:uploaded_file][:tempfile].size
32
+ ]
31
33
  else
32
34
  status 400
33
35
  end
@@ -0,0 +1 @@
1
+ ファイル
@@ -67,7 +67,7 @@ class RequestMiddlewareTest < Faraday::TestCase
67
67
  response = @conn.post('/echo', {:str => "eé cç aã aâ"})
68
68
  assert_equal "str=e%C3%A9+c%C3%A7+a%C3%A3+a%C3%A2", response.body
69
69
  }
70
- assert err.empty?
70
+ assert err.empty?, "stderr did include: #{err}"
71
71
  end
72
72
 
73
73
  def test_url_encoded_unicode_with_kcode_set
@@ -76,7 +76,7 @@ class RequestMiddlewareTest < Faraday::TestCase
76
76
  response = @conn.post('/echo', {:str => "eé cç aã aâ"})
77
77
  assert_equal "str=e%C3%A9+c%C3%A7+a%C3%A3+a%C3%A2", response.body
78
78
  }
79
- assert err.empty?
79
+ assert err.empty?, "stderr did include: #{err}"
80
80
  end
81
81
  end
82
82
 
@@ -96,7 +96,7 @@ class RequestMiddlewareTest < Faraday::TestCase
96
96
  response = @conn.post('/echo', payload)
97
97
 
98
98
  assert_kind_of Faraday::CompositeReadIO, response.body
99
- assert_equal "multipart/form-data;boundary=%s" % Faraday::Request::Multipart::DEFAULT_BOUNDARY,
99
+ assert_equal "multipart/form-data; boundary=%s" % Faraday::Request::Multipart::DEFAULT_BOUNDARY,
100
100
  response.headers['Content-Type']
101
101
 
102
102
  response.body.send(:ios).map{|io| io.read}.each do |io|
@@ -106,7 +106,7 @@ class RequestMiddlewareTest < Faraday::TestCase
106
106
  end
107
107
  assert_equal [], regexes
108
108
  end
109
-
109
+
110
110
  def test_multipart_with_arrays
111
111
  # assume params are out of order
112
112
  regexes = [
@@ -118,7 +118,7 @@ class RequestMiddlewareTest < Faraday::TestCase
118
118
  response = @conn.post('/echo', payload)
119
119
 
120
120
  assert_kind_of Faraday::CompositeReadIO, response.body
121
- assert_equal "multipart/form-data;boundary=%s" % Faraday::Request::Multipart::DEFAULT_BOUNDARY,
121
+ assert_equal "multipart/form-data; boundary=%s" % Faraday::Request::Multipart::DEFAULT_BOUNDARY,
122
122
  response.headers['Content-Type']
123
123
 
124
124
  response.body.send(:ios).map{|io| io.read}.each do |io|
@@ -128,5 +128,5 @@ class RequestMiddlewareTest < Faraday::TestCase
128
128
  end
129
129
  assert_equal [], regexes
130
130
  end
131
-
131
+
132
132
  end
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ class TestUtils < Faraday::TestCase
4
+
5
+ # emulates ActiveSupport::SafeBuffer#gsub
6
+ FakeSafeBuffer = Struct.new(:string) do
7
+ def to_s() self end
8
+ def gsub(regex)
9
+ string.gsub(regex) {
10
+ match, = $&, '' =~ /a/
11
+ yield match
12
+ }
13
+ end
14
+ end
15
+
16
+ def test_escaping_safe_buffer
17
+ str = FakeSafeBuffer.new('$32,000.00')
18
+ assert_equal '%2432%2C000.00', Faraday::Utils.escape(str)
19
+ end
20
+
21
+ end
22
+
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.8.7
4
+ version: 0.8.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-24 00:00:00.000000000 Z
12
+ date: 2013-07-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multipart-post
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '1.1'
21
+ version: 1.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: '1.1'
29
+ version: 1.2.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +119,11 @@ files:
119
119
  - test/middleware_stack_test.rb
120
120
  - test/request_middleware_test.rb
121
121
  - test/response_middleware_test.rb
122
+ - test/utils_test.rb
123
+ - test/multibyte.txt
124
+ - script/generate_certs
125
+ - script/proxy-server
126
+ - script/server
122
127
  - script/test
123
128
  homepage: https://github.com/lostisland/faraday
124
129
  licenses: