3 class Typhoeus < Faraday::Adapter
4 self.supports_parallel = true
6 def self.setup_parallel_manager(options = {})
7 options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options)
18 def perform_request(env)
21 hydra = env[:parallel_manager] || self.class.setup_parallel_manager
22 hydra.queue request(env)
23 hydra.run unless parallel?(env)
24 rescue Errno::ECONNREFUSED
25 raise Error::ConnectionFailed, $!
28 # TODO: support streaming requests
30 env[:body] = env[:body].read if env[:body].respond_to? :read
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
39 req = ::Typhoeus::Request.new env[:url].to_s,
42 :headers => env[:request_headers],
43 :disable_ssl_peer_verification => (env[:ssl] && env[:ssl].disable?)
45 configure_ssl req, env
46 configure_proxy req, env
47 configure_timeout req, env
48 configure_socket req, env
50 req.on_complete do |resp|
53 # TODO: error callback in async mode
55 raise Faraday::Error::TimeoutError, "request timed out"
59 case resp.curl_return_code
63 raise Error::ConnectionFailed, resp.curl_error_message
65 raise Faraday::SSLError, resp.curl_error_message
67 raise Error::ClientError, resp.curl_error_message
70 save_response(env, resp.code, resp.body) do |response_headers|
71 response_headers.parse resp.headers
73 # in async mode, :response is initialized at this point
74 env[:response].finish(env) if parallel?(env)
80 def configure_ssl(req, env)
83 req.ssl_version = ssl[:version] if ssl[:version]
84 req.ssl_cert = ssl[:client_cert] if ssl[:client_cert]
85 req.ssl_key = ssl[:client_key] if ssl[:client_key]
86 req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file]
87 req.ssl_capath = ssl[:ca_path] if ssl[:ca_path]
90 def configure_proxy(req, env)
91 proxy = request_options(env)[:proxy]
94 req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}"
96 if proxy[:user] && proxy[:password]
97 req.proxy_username = proxy[:user]
98 req.proxy_password = proxy[:password]
102 def configure_timeout(req, env)
103 env_req = request_options(env)
104 req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout]
105 req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout]
108 def configure_socket(req, env)
109 if bind = request_options(env)[:bind]
110 req.interface = bind[:host]
114 def request_options(env)
119 !!env[:parallel_manager]