Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

507 typhoeus faraday adapter expects client key and client cert to be filename #619

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,36 @@ end
This will properly stop the stream internally and avoid any memory leak which
may happen if you interrupt with something like a `return`, `throw` or `raise`.

### Usage with Faraday

Typhoeus includes a [Faraday](https://github.com/lostisland/faraday) adapter.

```ruby
conn = Faraday.new(:url => 'http://httppage.com') do |builder|
# Other Faraday middlewares...
builder.adapter :typhoeus # must be last
end

# OR

Faraday.default_adapter = :typhoeus

conn = Faraday.new(:url => 'http://httppage.com') do |builder|
# Other Faraday middlewares...
builder.adapter Faraday.default_adapter # must be last
end
```

One caveat is that, unlike some other Faraday adapters, Typhoeus expects client certificates and keys to be the path to the files rather than the files themselves, and will raise a `PathExpectedError` if you configure these with files.

```ruby
conn = Faraday.new(:url => '...', :ssl_options => { :client_cert => OpenSSL::X509::Certificate.new(File.read(cert_path)) })
# => raises Faraday::Adapter::Typhoeus::PathExpectedError

conn = Faraday.new(:url => '...', :ssl_options => { :client_cert => cert_path })
# => works
```

### Making Parallel Requests

Generally, you should be running requests through hydra. Here is how that looks:
Expand Down
5 changes: 5 additions & 0 deletions lib/typhoeus/adapters/faraday.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class Typhoeus < Faraday::Adapter
remove_method :configure_socket if method_defined? :configure_socket
remove_method :parallel? if method_defined? :parallel?

PathExpectedError = Class.new(StandardError)

# Initialize the Typhoeus adapter
#
# @param [ App ] app Farday app
Expand Down Expand Up @@ -134,6 +136,9 @@ def read_body(env)
def configure_ssl(req, env)
ssl = env[:ssl]

raise PathExpectedError, 'Typhoeus expects a path for `client_cert`' unless ssl.fetch(:client_cert, '').is_a? String
raise PathExpectedError, 'Typhoeus expects a path for `client_key`' unless ssl.fetch(:client_key, '').is_a? String

verify_p = (ssl && ssl.fetch(:verify, true))

ssl_verifyhost = verify_p ? 2 : 0
Expand Down
129 changes: 76 additions & 53 deletions spec/typhoeus/adapters/faraday_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -227,93 +227,116 @@
end

describe "#configure_ssl" do
before { adapter.method(:configure_ssl).call(request, env) }
context "with valid arguments" do
before { adapter.method(:configure_ssl).call(request, env) }

context "when version" do
let(:env) { { :ssl => { :version => "a" } } }
context "when version" do
let(:env) { { :ssl => { :version => "a" } } }

it "sets sslversion" do
expect(request.options[:sslversion]).to eq("a")
it "sets sslversion" do
expect(request.options[:sslversion]).to eq("a")
end
end
end

context "when client_cert" do
let(:env) { { :ssl => { :client_cert => "a" } } }
context "when client_cert" do
let(:env) { { :ssl => { :client_cert => "a" } } }

it "sets sslcert" do
expect(request.options[:sslcert]).to eq("a")
it "sets sslcert" do
expect(request.options[:sslcert]).to eq("a")
end
end
end

context "when client_key" do
let(:env) { { :ssl => { :client_key => "a" } } }
context "when client_key" do
let(:env) { { :ssl => { :client_key => "a" } } }

it "sets sslkey" do
expect(request.options[:sslkey]).to eq("a")
it "sets sslkey" do
expect(request.options[:sslkey]).to eq("a")
end
end
end

context "when ca_file" do
let(:env) { { :ssl => { :ca_file => "a" } } }
context "when ca_file" do
let(:env) { { :ssl => { :ca_file => "a" } } }

it "sets cainfo" do
expect(request.options[:cainfo]).to eq("a")
it "sets cainfo" do
expect(request.options[:cainfo]).to eq("a")
end
end
end

context "when ca_path" do
let(:env) { { :ssl => { :ca_path => "a" } } }
context "when ca_path" do
let(:env) { { :ssl => { :ca_path => "a" } } }

it "sets capath" do
expect(request.options[:capath]).to eq("a")
it "sets capath" do
expect(request.options[:capath]).to eq("a")
end
end
end

context "when client_cert_passwd" do
let(:env) { { :ssl => { :client_cert_passwd => "a" } } }
context "when client_cert_passwd" do
let(:env) { { :ssl => { :client_cert_passwd => "a" } } }

it "sets keypasswd to the value of client_cert_passwd" do
expect(request.options[:keypasswd]).to eq("a")
it "sets keypasswd to the value of client_cert_passwd" do
expect(request.options[:keypasswd]).to eq("a")
end
end
end

context "when client_certificate_password" do
let(:env) { { :ssl => { :client_certificate_password => "a" } } }
context "when client_certificate_password" do
let(:env) { { :ssl => { :client_certificate_password => "a" } } }

it "sets keypasswd to the value of client_cert_passwd" do
expect(request.options[:keypasswd]).to eq("a")
it "sets keypasswd to the value of client_cert_passwd" do
expect(request.options[:keypasswd]).to eq("a")
end
end
end

context "when no client_cert_passwd" do
let(:env) { { :ssl => { } } }
context "when no client_cert_passwd" do
let(:env) { { :ssl => { } } }

it "does not set keypasswd on options" do
expect(request.options).not_to have_key :keypasswd
it "does not set keypasswd on options" do
expect(request.options).not_to have_key :keypasswd
end
end
end

context "when verify is false" do
let(:env) { { :ssl => { :verify => false } } }
context "when verify is false" do
let(:env) { { :ssl => { :verify => false } } }

it "sets ssl_verifyhost to 0" do
expect(request.options[:ssl_verifyhost]).to eq(0)
end

it "sets ssl_verifyhost to 0" do
expect(request.options[:ssl_verifyhost]).to eq(0)
it "sets ssl_verifypeer to false" do
expect(request.options[:ssl_verifypeer]).to be_falsey
end
end

it "sets ssl_verifypeer to false" do
expect(request.options[:ssl_verifypeer]).to be_falsey
context "when verify is true" do
let(:env) { { :ssl => { :verify => true } } }

it "sets ssl_verifyhost to 2" do
expect(request.options[:ssl_verifyhost]).to eq(2)
end

it "sets ssl_verifypeer to true" do
expect(request.options[:ssl_verifypeer]).to be_truthy
end
end
end

context "when verify is true" do
let(:env) { { :ssl => { :verify => true } } }
context "with invalid arguments" do
subject { adapter.method(:configure_ssl).call(request, env) }

it "sets ssl_verifyhost to 2" do
expect(request.options[:ssl_verifyhost]).to eq(2)
context "when a non-path (non-String) is given for the client cert" do
let(:env) { { :ssl => { :client_cert => Hash.new('pretend_im_a_file') } } }

it "raises a PathExpectedError" do
expect { subject }.to raise_error Faraday::Adapter::Typhoeus::PathExpectedError
end
end

it "sets ssl_verifypeer to true" do
expect(request.options[:ssl_verifypeer]).to be_truthy

context "when a non-path (non-String) is given for the client key" do
let(:env) { { :ssl => { :client_key => Hash.new('pretend_im_a_file') } } }

it "raises a PathExpectedError" do
expect { subject }.to raise_error Faraday::Adapter::Typhoeus::PathExpectedError
end
end
end
end
Expand Down