faraday 0.8.11 → 0.9.0

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/.document +6 -0
  3. data/CHANGELOG.md +15 -0
  4. data/CONTRIBUTING.md +36 -0
  5. data/Gemfile +10 -3
  6. data/LICENSE.md +1 -1
  7. data/README.md +17 -51
  8. data/Rakefile +2 -18
  9. data/faraday.gemspec +34 -0
  10. data/lib/faraday/adapter/em_http.rb +34 -0
  11. data/lib/faraday/adapter/em_http_ssl_patch.rb +56 -0
  12. data/lib/faraday/adapter/em_synchrony.rb +11 -24
  13. data/lib/faraday/adapter/excon.rb +12 -2
  14. data/lib/faraday/adapter/httpclient.rb +106 -0
  15. data/lib/faraday/adapter/net_http.rb +10 -6
  16. data/lib/faraday/adapter/patron.rb +2 -8
  17. data/lib/faraday/adapter/rack.rb +0 -2
  18. data/lib/faraday/adapter/test.rb +39 -39
  19. data/lib/faraday/adapter/typhoeus.rb +12 -3
  20. data/lib/faraday/adapter.rb +20 -35
  21. data/lib/faraday/autoload.rb +85 -0
  22. data/lib/faraday/connection.rb +232 -125
  23. data/lib/faraday/error.rb +42 -34
  24. data/lib/faraday/options.rb +350 -0
  25. data/lib/faraday/parameters.rb +193 -0
  26. data/lib/faraday/{builder.rb → rack_builder.rb} +79 -22
  27. data/lib/faraday/request/authorization.rb +7 -5
  28. data/lib/faraday/request/basic_authentication.rb +1 -1
  29. data/lib/faraday/request/instrumentation.rb +36 -0
  30. data/lib/faraday/request/multipart.rb +10 -9
  31. data/lib/faraday/request/retry.rb +99 -4
  32. data/lib/faraday/request/token_authentication.rb +2 -2
  33. data/lib/faraday/request/url_encoded.rb +7 -6
  34. data/lib/faraday/request.rb +21 -30
  35. data/lib/faraday/response/logger.rb +4 -4
  36. data/lib/faraday/response/raise_error.rb +4 -2
  37. data/lib/faraday/response.rb +17 -23
  38. data/lib/faraday/utils.rb +81 -71
  39. data/lib/faraday.rb +187 -68
  40. data/script/console +7 -0
  41. data/script/proxy-server +1 -0
  42. data/script/release +6 -3
  43. data/script/test +4 -2
  44. data/test/adapters/em_http_test.rb +6 -1
  45. data/test/adapters/em_synchrony_test.rb +7 -1
  46. data/test/adapters/httpclient_test.rb +21 -0
  47. data/test/adapters/integration.rb +23 -8
  48. data/test/adapters/logger_test.rb +1 -1
  49. data/test/adapters/net_http_persistent_test.rb +10 -1
  50. data/test/adapters/net_http_test.rb +0 -31
  51. data/test/adapters/patron_test.rb +4 -1
  52. data/test/adapters/test_middleware_test.rb +48 -4
  53. data/test/adapters/typhoeus_test.rb +8 -1
  54. data/test/authentication_middleware_test.rb +2 -2
  55. data/test/connection_test.rb +160 -84
  56. data/test/env_test.rb +51 -24
  57. data/test/helper.rb +13 -13
  58. data/test/live_server.rb +8 -0
  59. data/test/middleware/instrumentation_test.rb +88 -0
  60. data/test/middleware/retry_test.rb +88 -35
  61. data/test/middleware_stack_test.rb +13 -12
  62. data/test/options_test.rb +252 -0
  63. data/test/request_middleware_test.rb +11 -1
  64. data/test/response_middleware_test.rb +2 -4
  65. data/test/strawberry.rb +2 -0
  66. data/test/utils_test.rb +34 -6
  67. metadata +71 -11
  68. data/test/parameters_test.rb +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 431792ff21fb498eb658855f87503d2081869616
4
- data.tar.gz: c6b3a7f9c1a9f7a4a60eff2236b882dbd812eab4
3
+ metadata.gz: 0e442daff424089e143751d7cb1d684c169bf4fc
4
+ data.tar.gz: ba1dd50171576d5064350e48b8869364c0710a26
5
5
  SHA512:
6
- metadata.gz: 8855727969169984a104ba02c2ed27b4a86fb7d3a698fe6f5932c4858cb5e4f5eba9251d3742cb8d999b654f89ff2d073228738998f3199ae104e9e9883bd031
7
- data.tar.gz: eda459cc1abe00450f0d48dab3b069544dd414001faf9be231e2215fa81efced7496a99a2baa6502f1d7bbe162f6b41f415cdef1cd9ce935a9de8752749997a3
6
+ metadata.gz: 80c7a955f7d0a2217fcde0be2760649b9e5fc2d950929b118383ba61ea7282410b224315e289b40fec12be13898b0b00551e441704462ac39269368a8f9d5931
7
+ data.tar.gz: cdef47ebdb9519d0e45e7511326ed1368fa520ad314a4055ea154187193c967f8821573705161e3bbca5d3cbbf40f219071223ba8d24821c5dd89e37ddd16a9e
data/.document ADDED
@@ -0,0 +1,6 @@
1
+ CONTRIBUTING.md
2
+ LICENSE.md
3
+ README.md
4
+ bin/*
5
+ lib/**/*.rb
6
+ test/**/*.rb
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # Faraday Changelog
2
+
3
+ ## v0.9.0
4
+
5
+ * Add HTTPClient adapter (@hakanensari)
6
+ * Improve Retry handler (@mislav)
7
+ * Remove autoloading by default (@technoweenie)
8
+ * Improve internal docs (@technoweenie, @mislav)
9
+ * Respect user/password in http proxy string (@mislav)
10
+ * Adapter options are structs. Reinforces consistent options across adapters
11
+ (@technoweenie)
12
+ * Stop stripping trailing / off base URLs in a Faraday::Connection. (@technoweenie)
13
+ * Add a configurable URI parser. (@technoweenie)
14
+ * Remove need to manually autoload when using the authorization header helpers on `Faraday::Connection`. (@technoweenie)
15
+ * `Faraday::Adapter::Test` respects the `Faraday::RequestOptions#params_encoder` option. (@technoweenie)
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,36 @@
1
+ ## Contributing
2
+
3
+ You can run the test suite against a live server by running `script/test`. It
4
+ automatically starts a test server in background. Only tests in
5
+ `test/adapters/*_test.rb` require a server, though.
6
+
7
+ ``` sh
8
+ # run the whole suite
9
+ $ script/test
10
+
11
+ # run only specific files
12
+ $ script/test excon typhoeus
13
+
14
+ # run tests using SSL
15
+ $ SSL=yes script/test
16
+ ```
17
+
18
+ We will accept middleware that:
19
+
20
+ 1. is useful to a broader audience, but can be implemented relatively
21
+ simple; and
22
+ 2. which isn't already present in [faraday_middleware][] project.
23
+
24
+ We will accept adapters that:
25
+
26
+ 1. support SSL & streaming;
27
+ 1. are proven and may have better performance than existing ones; or
28
+ 2. if they have features not present in included adapters.
29
+
30
+ We are pushing towards a 1.0 release, when we will have to follow [Semantic
31
+ Versioning][semver]. If your patch includes changes to break compatiblitity,
32
+ note that so we can add it to the [Changelog][].
33
+
34
+ [semver]: http://semver.org/
35
+ [changelog]: https://github.com/technoweenie/faraday/wiki/Changelog
36
+ [faraday_middleware]: https://github.com/pengwynn/faraday_middleware/wiki
data/Gemfile CHANGED
@@ -5,18 +5,25 @@ gem 'jruby-openssl', '~> 0.8.8', :platforms => :jruby
5
5
  gem 'rake'
6
6
 
7
7
  group :test do
8
- gem 'test-unit'
8
+ gem 'coveralls', :require => false
9
9
  gem 'em-http-request', '>= 1.1', :require => 'em-http'
10
- gem 'em-synchrony', '>= 1.0', :require => ['em-synchrony', 'em-synchrony/em-http']
10
+ gem 'em-synchrony', '>= 1.0.3', :require => ['em-synchrony', 'em-synchrony/em-http']
11
11
  gem 'excon', '>= 0.27.4'
12
+ gem 'httpclient', '>= 2.2'
12
13
  gem 'leftright', '>= 0.9', :require => false
13
14
  gem 'mime-types', '~> 1.25', :platforms => [:jruby, :ruby_18]
15
+ gem 'minitest', '>= 5.0.5'
14
16
  gem 'net-http-persistent', '>= 2.5', :require => false
15
17
  gem 'patron', '>= 0.4.2', :platforms => :ruby
16
18
  gem 'rack-test', '>= 0.6', :require => 'rack/test'
17
19
  gem 'simplecov'
18
20
  gem 'sinatra', '~> 1.3'
19
- gem 'typhoeus', '~> 0.3.3', :platforms => [:ruby_18, :ruby_19, :ruby_20, :ruby_21]
21
+ gem 'typhoeus', '~> 0.3.3', :platforms => :ruby
22
+ end
23
+
24
+ platforms :rbx do
25
+ gem 'rubinius-coverage'
26
+ gem 'rubysl'
20
27
  end
21
28
 
22
29
  gemspec
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 rick olson, zack hobson
1
+ Copyright (c) 2009-2013 Rick Olson, Zack Hobson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -51,8 +51,8 @@ end
51
51
 
52
52
  conn.get do |req|
53
53
  req.url '/search'
54
- req.options[:timeout] = 5 # open/read timeout in seconds
55
- req.options[:open_timeout] = 2 # connection open timeout in seconds
54
+ req.options.timeout = 5 # open/read timeout in seconds
55
+ req.options.open_timeout = 2 # connection open timeout in seconds
56
56
  end
57
57
  ```
58
58
 
@@ -175,36 +175,6 @@ stubs.verify_stubbed_calls
175
175
  * support streaming requests/responses
176
176
  * better stubbing API
177
177
 
178
- ## Contributing
179
-
180
- You can run the test suite against a live server by running `script/test`. It
181
- automatically starts a test server in background. Only tests in
182
- `test/adapters/*_test.rb` require a server, though.
183
-
184
- ``` sh
185
- # run the whole suite
186
- $ script/test
187
-
188
- # run only specific files
189
- $ script/test excon typhoeus
190
- ```
191
-
192
- We will accept middleware that:
193
-
194
- 1. is useful to a broader audience, but can be implemented relatively
195
- simple; and
196
- 2. which isn't already present in [faraday_middleware][] project.
197
-
198
- We will accept adapters that:
199
-
200
- 1. support SSL & streaming;
201
- 1. are proven and may have better performance than existing ones; or
202
- 2. if they have features not present in included adapters.
203
-
204
- We are pushing towards a 1.0 release, when we will have to follow [Semantic
205
- Versioning][semver]. If your patch includes changes to break compatiblitity,
206
- note that so we can add it to the [Changelog][].
207
-
208
178
  ## Supported Ruby versions
209
179
 
210
180
  This library aims to support and is [tested against][travis] the following Ruby
@@ -213,11 +183,12 @@ implementations:
213
183
  * MRI 1.8.7
214
184
  * MRI 1.9.2
215
185
  * MRI 1.9.3
186
+ * MRI 2.0.0
187
+ * MRI 2.1.0
216
188
  * [JRuby][]
217
189
  * [Rubinius][]
218
190
 
219
- If something doesn't work on one of these interpreters, it should be considered
220
- a bug.
191
+ If something doesn't work on one of these Ruby versions, it's a bug.
221
192
 
222
193
  This library may inadvertently work (or seem to work) on other Ruby
223
194
  implementations, however support will only be provided for the versions listed
@@ -226,25 +197,20 @@ above.
226
197
  If you would like this library to support another Ruby version, you may
227
198
  volunteer to be a maintainer. Being a maintainer entails making sure all tests
228
199
  run and pass on that implementation. When something breaks on your
229
- implementation, you will be personally responsible for providing patches in a
230
- timely fashion. If critical issues for a particular implementation exist at the
231
- time of a major release, support for that Ruby version may be dropped.
200
+ implementation, you will be responsible for providing patches in a timely
201
+ fashion. If critical issues for a particular implementation exist at the time
202
+ of a major release, support for that Ruby version may be dropped.
232
203
 
233
204
  ## Copyright
234
205
 
235
- Copyright (c) 2009-2012 [Rick Olson](mailto:technoweenie@gmail.com), zack hobson.
206
+ Copyright (c) 2009-2013 [Rick Olson](mailto:technoweenie@gmail.com), Zack Hobson.
236
207
  See [LICENSE][] for details.
237
208
 
238
-
239
- [license]: https://github.com/technoweenie/faraday/blob/master/LICENSE.md
240
- [travis]: http://travis-ci.org/technoweenie/faraday
241
- [jruby]: http://jruby.org/
242
- [rubinius]: http://rubini.us/
243
- [semver]: http://semver.org/
244
- [changelog]: https://github.com/technoweenie/faraday/wiki/Changelog
245
- [excon]: https://github.com/geemus/excon#readme
246
- [typhoeus]: https://github.com/typhoeus/typhoeus#readme
247
- [patron]: http://toland.github.com/patron/
248
-
249
- [eventmachine]: https://github.com/igrigorik/em-http-request#readme
250
- [faraday_middleware]: https://github.com/pengwynn/faraday_middleware/wiki
209
+ [travis]: http://travis-ci.org/lostisland/faraday
210
+ [excon]: https://github.com/geemus/excon#readme
211
+ [typhoeus]: https://github.com/typhoeus/typhoeus#readme
212
+ [patron]: http://toland.github.com/patron/
213
+ [eventmachine]: https://github.com/igrigorik/em-http-request#readme
214
+ [jruby]: http://jruby.org/
215
+ [rubinius]: http://rubini.us/
216
+ [license]: LICENSE.md
data/Rakefile CHANGED
@@ -2,6 +2,8 @@ require 'date'
2
2
  require 'fileutils'
3
3
  require 'openssl'
4
4
  require 'rake/testtask'
5
+ require 'bundler'
6
+ Bundler::GemHelper.install_tasks
5
7
 
6
8
  task :default => :test
7
9
 
@@ -67,21 +69,3 @@ desc "Open an irb session preloaded with this library"
67
69
  task :console do
68
70
  sh "irb -rubygems -r ./lib/#{name}.rb"
69
71
  end
70
-
71
- ## release management tasks
72
-
73
- desc "Commit, create tag v#{version} and build and push #{gem_file} to Rubygems"
74
- task :release => :build do
75
- sh "git commit --allow-empty -a -m 'Release #{version}'"
76
- sh "git tag v#{version}"
77
- sh "git push origin"
78
- sh "git push origin v#{version}"
79
- sh "gem push pkg/#{gem_file}"
80
- end
81
-
82
- desc "Build #{gem_file} into the pkg directory"
83
- task :build do
84
- FileUtils.mkdir_p 'pkg'
85
- sh "gem build #{gemspec_file}"
86
- sh "mv #{gem_file} pkg"
87
- end
data/faraday.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ lib = "faraday"
2
+ lib_file = File.expand_path("../lib/#{lib}.rb", __FILE__)
3
+ File.read(lib_file) =~ /\bVERSION\s*=\s*["'](.+?)["']/
4
+ version = $1
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.specification_version = 2 if spec.respond_to? :specification_version=
8
+ spec.required_rubygems_version = '>= 1.3.5'
9
+
10
+ spec.name = lib
11
+ spec.version = version
12
+
13
+ spec.summary = "HTTP/REST API client library."
14
+
15
+ spec.authors = ["Rick Olson"]
16
+ spec.email = 'technoweenie@gmail.com'
17
+ spec.homepage = 'https://github.com/lostisland/faraday'
18
+ spec.licenses = ['MIT']
19
+
20
+ spec.add_dependency 'multipart-post', '>= 1.2', '< 3'
21
+ spec.add_development_dependency 'bundler', '~> 1.0'
22
+
23
+ spec.files = %w(.document CHANGELOG.md CONTRIBUTING.md Gemfile LICENSE.md README.md Rakefile)
24
+ spec.files << "#{lib}.gemspec"
25
+ spec.files += Dir.glob("lib/**/*.rb")
26
+ spec.files += Dir.glob("test/**/*.{rb,txt}")
27
+ spec.files += Dir.glob("script/*")
28
+
29
+ dev_null = File.exist?('/dev/null') ? '/dev/null' : 'NUL'
30
+ git_files = `git ls-files -z 2>#{dev_null}`
31
+ spec.files &= git_files.split("\0") if $?.success?
32
+
33
+ spec.test_files = Dir.glob("test/**/*.rb")
34
+ end
@@ -9,6 +9,8 @@ module Faraday
9
9
  options = {}
10
10
  configure_proxy(options, env)
11
11
  configure_timeout(options, env)
12
+ configure_socket(options, env)
13
+ configure_ssl(options, env)
12
14
  options
13
15
  end
14
16
 
@@ -38,6 +40,24 @@ module Faraday
38
40
  end
39
41
  end
40
42
 
43
+ def configure_socket(options, env)
44
+ if bind = request_options(env)[:bind]
45
+ options[:bind] = {
46
+ :host => bind[:host],
47
+ :port => bind[:port]
48
+ }
49
+ end
50
+ end
51
+
52
+ def configure_ssl(options, env)
53
+ if env[:url].scheme == 'https' && env[:ssl]
54
+ options[:ssl] = {
55
+ :cert_chain_file => env[:ssl][:ca_file],
56
+ :verify_peer => env[:ssl].fetch(:verify, true)
57
+ }
58
+ end
59
+ end
60
+
41
61
  def configure_timeout(options, env)
42
62
  timeout, open_timeout = request_options(env).values_at(:timeout, :open_timeout)
43
63
  options[:connect_timeout] = options[:inactivity_timeout] = timeout
@@ -108,6 +128,12 @@ module Faraday
108
128
  else
109
129
  raise Error::ConnectionFailed, err
110
130
  end
131
+ rescue => err
132
+ if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
133
+ raise Faraday::SSLError, err
134
+ else
135
+ raise
136
+ end
111
137
  end
112
138
 
113
139
  # TODO: reuse the connection to support pipelining
@@ -201,3 +227,11 @@ module Faraday
201
227
  end
202
228
  end
203
229
  end
230
+
231
+ begin
232
+ require 'openssl'
233
+ rescue LoadError
234
+ warn "Warning: no such file to load -- openssl. Make sure it is installed if you want HTTPS support"
235
+ else
236
+ require 'faraday/adapter/em_http_ssl_patch'
237
+ end if Faraday::Adapter::EMHttp.loaded?
@@ -0,0 +1,56 @@
1
+ require 'openssl'
2
+ require 'em-http'
3
+
4
+ module EmHttpSslPatch
5
+ def ssl_verify_peer(cert_string)
6
+ cert = nil
7
+ begin
8
+ cert = OpenSSL::X509::Certificate.new(cert_string)
9
+ rescue OpenSSL::X509::CertificateError
10
+ return false
11
+ end
12
+
13
+ @last_seen_cert = cert
14
+
15
+ if certificate_store.verify(@last_seen_cert)
16
+ begin
17
+ certificate_store.add_cert(@last_seen_cert)
18
+ rescue OpenSSL::X509::StoreError => e
19
+ raise e unless e.message == 'cert already in hash table'
20
+ end
21
+ true
22
+ else
23
+ raise OpenSSL::SSL::SSLError.new(%(unable to verify the server certificate for "#{host}"))
24
+ end
25
+ end
26
+
27
+ def ssl_handshake_completed
28
+ return true unless verify_peer?
29
+
30
+ unless OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, host)
31
+ raise OpenSSL::SSL::SSLError.new(%(host "#{host}" does not match the server certificate))
32
+ else
33
+ true
34
+ end
35
+ end
36
+
37
+ def verify_peer?
38
+ parent.connopts.tls[:verify_peer]
39
+ end
40
+
41
+ def host
42
+ parent.connopts.host
43
+ end
44
+
45
+ def certificate_store
46
+ @certificate_store ||= begin
47
+ store = OpenSSL::X509::Store.new
48
+ store.set_default_paths
49
+ ca_file = parent.connopts.tls[:cert_chain_file]
50
+ store.add_file(ca_file) if ca_file
51
+ store
52
+ end
53
+ end
54
+ end
55
+
56
+ EventMachine::HttpStubConnection.send(:include, EmHttpSslPatch)
@@ -19,7 +19,7 @@ module Faraday
19
19
 
20
20
  def call(env)
21
21
  super
22
- request = EventMachine::HttpRequest.new(URI::parse(env[:url].to_s), connection_config(env)) # end
22
+ request = EventMachine::HttpRequest.new(Utils::URI(env[:url].to_s), connection_config(env))
23
23
 
24
24
  http_method = env[:method].to_s.downcase.to_sym
25
25
 
@@ -70,9 +70,9 @@ module Faraday
70
70
  else
71
71
  raise Error::ConnectionFailed, err
72
72
  end
73
- rescue RuntimeError => err
74
- if err.message == "connection closed by server"
75
- raise Error::ConnectionFailed, err
73
+ rescue => err
74
+ if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
75
+ raise Faraday::SSLError, err
76
76
  else
77
77
  raise
78
78
  end
@@ -83,23 +83,10 @@ end
83
83
 
84
84
  require 'faraday/adapter/em_synchrony/parallel_manager'
85
85
 
86
- # add missing patch(), options() methods
87
- EventMachine::HTTPMethods.module_eval do
88
- [:patch, :options].each do |type|
89
- next if method_defined? :"a#{type}"
90
- alias_method :"a#{type}", type if method_defined? type
91
- module_eval %[
92
- def #{type}(options = {}, &blk)
93
- f = Fiber.current
94
- conn = setup_request(:#{type}, options, &blk)
95
- if conn.error.nil?
96
- conn.callback { f.resume(conn) }
97
- conn.errback { f.resume(conn) }
98
- Fiber.yield
99
- else
100
- conn
101
- end
102
- end
103
- ]
104
- end
105
- end
86
+ begin
87
+ require 'openssl'
88
+ rescue LoadError
89
+ warn "Warning: no such file to load -- openssl. Make sure it is installed if you want HTTPS support"
90
+ else
91
+ require 'faraday/adapter/em_http_ssl_patch'
92
+ end if Faraday::Adapter::EMSynchrony.loaded?
@@ -3,6 +3,11 @@ module Faraday
3
3
  class Excon < Faraday::Adapter
4
4
  dependency 'excon'
5
5
 
6
+ def initialize(app, connection_options = {})
7
+ @connection_options = connection_options
8
+ super(app)
9
+ end
10
+
6
11
  def call(env)
7
12
  super
8
13
 
@@ -11,6 +16,10 @@ module Faraday
11
16
  opts[:ssl_verify_peer] = !!ssl.fetch(:verify, true)
12
17
  opts[:ssl_ca_path] = ssl[:ca_path] if ssl[:ca_path]
13
18
  opts[:ssl_ca_file] = ssl[:ca_file] if ssl[:ca_file]
19
+ opts[:client_cert] = ssl[:client_cert] if ssl[:client_cert]
20
+ opts[:client_key] = ssl[:client_key] if ssl[:client_key]
21
+ opts[:certificate] = ssl[:certificate] if ssl[:certificate]
22
+ opts[:private_key] = ssl[:private_key] if ssl[:private_key]
14
23
 
15
24
  # https://github.com/geemus/excon/issues/106
16
25
  # https://github.com/jruby/jruby-ossl/issues/19
@@ -32,7 +41,6 @@ module Faraday
32
41
  if req[:proxy]
33
42
  opts[:proxy] = {
34
43
  :host => req[:proxy][:uri].host,
35
- :hostname => req[:proxy][:uri].hostname,
36
44
  :port => req[:proxy][:uri].port,
37
45
  :scheme => req[:proxy][:uri].scheme,
38
46
  :user => req[:proxy][:user],
@@ -41,7 +49,7 @@ module Faraday
41
49
  end
42
50
  end
43
51
 
44
- conn = ::Excon.new(env[:url].to_s, opts)
52
+ conn = ::Excon.new(env[:url].to_s, opts.merge(@connection_options))
45
53
 
46
54
  resp = conn.request \
47
55
  :method => env[:method].to_s.upcase,
@@ -54,6 +62,8 @@ module Faraday
54
62
  rescue ::Excon::Errors::SocketError => err
55
63
  if err.message =~ /\btimeout\b/
56
64
  raise Error::TimeoutError, err
65
+ elsif err.message =~ /\bcertificate\b/
66
+ raise Faraday::SSLError, err
57
67
  else
58
68
  raise Error::ConnectionFailed, err
59
69
  end
@@ -0,0 +1,106 @@
1
+ module Faraday
2
+ class Adapter
3
+ class HTTPClient < Faraday::Adapter
4
+ dependency 'httpclient'
5
+
6
+ def client
7
+ @client ||= ::HTTPClient.new
8
+ end
9
+
10
+ def call(env)
11
+ super
12
+
13
+ if req = env[:request]
14
+ if proxy = req[:proxy]
15
+ configure_proxy proxy
16
+ end
17
+
18
+ if bind = req[:bind]
19
+ configure_socket bind
20
+ end
21
+
22
+ configure_timeouts req
23
+ end
24
+
25
+ if env[:url].scheme == 'https' && ssl = env[:ssl]
26
+ configure_ssl ssl
27
+ end
28
+
29
+ # TODO Don't stream yet.
30
+ # https://github.com/nahi/httpclient/pull/90
31
+ env[:body] = env[:body].read if env[:body].respond_to? :read
32
+
33
+ resp = client.request env[:method], env[:url],
34
+ :body => env[:body],
35
+ :header => env[:request_headers]
36
+
37
+ save_response env, resp.status, resp.body, resp.headers
38
+
39
+ @app.call env
40
+ rescue ::HTTPClient::TimeoutError
41
+ raise Faraday::Error::TimeoutError, $!
42
+ rescue ::HTTPClient::BadResponseError => err
43
+ if err.message.include?('status 407')
44
+ raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "}
45
+ else
46
+ raise Faraday::Error::ClientError, $!
47
+ end
48
+ rescue Errno::ECONNREFUSED, EOFError
49
+ raise Faraday::Error::ConnectionFailed, $!
50
+ rescue => err
51
+ if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
52
+ raise Faraday::SSLError, err
53
+ else
54
+ raise
55
+ end
56
+ end
57
+
58
+ def configure_socket(bind)
59
+ client.socket_local.host = bind[:host]
60
+ client.socket_local.port = bind[:port]
61
+ end
62
+
63
+ def configure_proxy(proxy)
64
+ client.proxy = proxy[:uri]
65
+ if proxy[:user] && proxy[:password]
66
+ client.set_proxy_auth proxy[:user], proxy[:password]
67
+ end
68
+ end
69
+
70
+ def configure_ssl(ssl)
71
+ ssl_config = client.ssl_config
72
+
73
+ ssl_config.add_trust_ca ssl[:ca_file] if ssl[:ca_file]
74
+ ssl_config.add_trust_ca ssl[:ca_path] if ssl[:ca_path]
75
+ ssl_config.cert_store = ssl[:cert_store] if ssl[:cert_store]
76
+ ssl_config.client_cert = ssl[:client_cert] if ssl[:client_cert]
77
+ ssl_config.client_key = ssl[:client_key] if ssl[:client_key]
78
+ ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth]
79
+ ssl_config.verify_mode = ssl_verify_mode(ssl)
80
+ end
81
+
82
+ def configure_timeouts(req)
83
+ if req[:timeout]
84
+ client.connect_timeout = req[:timeout]
85
+ client.receive_timeout = req[:timeout]
86
+ client.send_timeout = req[:timeout]
87
+ end
88
+
89
+ if req[:open_timeout]
90
+ client.connect_timeout = req[:open_timeout]
91
+ client.send_timeout = req[:open_timeout]
92
+ end
93
+ end
94
+
95
+ def ssl_verify_mode(ssl)
96
+ ssl[:verify_mode] || begin
97
+ if ssl.fetch(:verify, true)
98
+ OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
99
+ else
100
+ OpenSSL::SSL::VERIFY_NONE
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -13,9 +13,10 @@ module Faraday
13
13
  EOFError,
14
14
  Errno::ECONNABORTED,
15
15
  Errno::ECONNREFUSED,
16
- Errno::ENETUNREACH,
17
16
  Errno::ECONNRESET,
17
+ Errno::EHOSTUNREACH,
18
18
  Errno::EINVAL,
19
+ Errno::ENETUNREACH,
19
20
  Net::HTTPBadResponse,
20
21
  Net::HTTPHeaderSyntaxError,
21
22
  Net::ProtocolError,
@@ -24,7 +25,6 @@ module Faraday
24
25
  ]
25
26
 
26
27
  NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL)
27
- NET_HTTP_EXCEPTIONS << Net::OpenTimeout if defined?(Net::OpenTimeout)
28
28
 
29
29
  def call(env)
30
30
  super
@@ -37,11 +37,15 @@ module Faraday
37
37
 
38
38
  begin
39
39
  http_response = perform_request(http, env)
40
- rescue *NET_HTTP_EXCEPTIONS
41
- raise Error::ConnectionFailed, $!
40
+ rescue *NET_HTTP_EXCEPTIONS => err
41
+ if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err
42
+ raise Faraday::SSLError, err
43
+ else
44
+ raise Error::ConnectionFailed, err
45
+ end
42
46
  end
43
47
 
44
- save_response(env, http_response.code.to_i, http_response.body) do |response_headers|
48
+ save_response(env, http_response.code.to_i, http_response.body || '') do |response_headers|
45
49
  http_response.each_header do |key, value|
46
50
  response_headers[key] = value
47
51
  end
@@ -82,7 +86,7 @@ module Faraday
82
86
  Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
83
87
  else
84
88
  Net::HTTP
85
- end.new(env[:url].host, env[:url].port || (env[:url].scheme == 'https' ? 443 : 80))
89
+ end.new(env[:url].host, env[:url].port)
86
90
  end
87
91
 
88
92
  def configure_ssl(http, ssl)
@@ -52,14 +52,8 @@ module Faraday
52
52
  # HAX: helps but doesn't work completely
53
53
  # https://github.com/toland/patron/issues/34
54
54
  ::Patron::Request::VALID_ACTIONS.tap do |actions|
55
- if actions[0].is_a?(Symbol)
56
- actions << :patch unless actions.include? :patch
57
- actions << :options unless actions.include? :options
58
- else
59
- # Patron 0.4.20 and up
60
- actions << "PATCH" unless actions.include? "PATCH"
61
- actions << "OPTIONS" unless actions.include? "OPTIONS"
62
- end
55
+ actions << :patch unless actions.include? :patch
56
+ actions << :options unless actions.include? :options
63
57
  end
64
58
  end
65
59
 
@@ -1,5 +1,3 @@
1
- require 'timeout'
2
-
3
1
  module Faraday
4
2
  class Adapter
5
3
  # Sends requests to a Rack app.