+++ /dev/null
-module Faraday
- class Adapter
- class Typhoeus < Faraday::Adapter
- self.supports_parallel = true
-
- def self.setup_parallel_manager(options = {})
- options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options)
- end
-
- dependency 'typhoeus'
-
- def call(env)
- super
- perform_request env
- @app.call env
- end
-
- def perform_request(env)
- read_body env
-
- hydra = env[:parallel_manager] || self.class.setup_parallel_manager
- hydra.queue request(env)
- hydra.run unless parallel?(env)
- rescue Errno::ECONNREFUSED
- raise Error::ConnectionFailed, $!
- end
-
- # TODO: support streaming requests
- def read_body(env)
- env[:body] = env[:body].read if env[:body].respond_to? :read
- end
-
- def request(env)
- method = env[:method]
- # For some reason, prevents Typhoeus from using "100-continue".
- # We want this because Webrick 1.3.1 can't seem to handle it w/ PUT.
- method = method.to_s.upcase if method == :put
-
- req = ::Typhoeus::Request.new env[:url].to_s,
- :method => method,
- :body => env[:body],
- :headers => env[:request_headers],
- :disable_ssl_peer_verification => (env[:ssl] && env[:ssl].disable?)
-
- configure_ssl req, env
- configure_proxy req, env
- configure_timeout req, env
- configure_socket req, env
-
- req.on_complete do |resp|
- if resp.timed_out?
- if parallel?(env)
- # TODO: error callback in async mode
- else
- raise Faraday::Error::TimeoutError, "request timed out"
- end
- end
-
- case resp.curl_return_code
- when 0
- # everything OK
- when 7
- raise Error::ConnectionFailed, resp.curl_error_message
- when 60
- raise Faraday::SSLError, resp.curl_error_message
- else
- raise Error::ClientError, resp.curl_error_message
- end
-
- save_response(env, resp.code, resp.body) do |response_headers|
- response_headers.parse resp.headers
- end
- # in async mode, :response is initialized at this point
- env[:response].finish(env) if parallel?(env)
- end
-
- req
- end
-
- def configure_ssl(req, env)
- ssl = env[:ssl]
-
- req.ssl_version = ssl[:version] if ssl[:version]
- req.ssl_cert = ssl[:client_cert] if ssl[:client_cert]
- req.ssl_key = ssl[:client_key] if ssl[:client_key]
- req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file]
- req.ssl_capath = ssl[:ca_path] if ssl[:ca_path]
- end
-
- def configure_proxy(req, env)
- proxy = request_options(env)[:proxy]
- return unless proxy
-
- req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}"
-
- if proxy[:user] && proxy[:password]
- req.proxy_username = proxy[:user]
- req.proxy_password = proxy[:password]
- end
- end
-
- def configure_timeout(req, env)
- env_req = request_options(env)
- req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
- req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
- end
-
- def configure_socket(req, env)
- if bind = request_options(env)[:bind]
- req.interface = bind[:host]
- end
- end
-
- def request_options(env)
- env[:request]
- end
-
- def parallel?(env)
- !!env[:parallel_manager]
- end
- end
- end
-end