Skip to content

Commit

Permalink
Expose .connection on block param
Browse files Browse the repository at this point in the history
This provides access to the connection object,
which in turn exposes properties like `.peer_cert`
for performing additional validation against
x509 certificates.

Closes jnunemaker#633, Follow-up to jnunemaker#634
  • Loading branch information
machty committed Feb 19, 2019
1 parent 011c1ac commit 40204f2
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 12 deletions.
3 changes: 3 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,6 @@

* [Uploading File](body_stream.rb)
* Uses `body_stream` to upload file

* [Accessing x509 Peer Certificate](peer_cert.rb)
* Provides access to the server's TLS certificate
9 changes: 9 additions & 0 deletions examples/peer_cert.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
require File.join(dir, 'httparty')

peer_cert = nil
HTTParty.get("https://www.example.com") do |fragment|
peer_cert ||= fragment.connection.peer_cert
end

puts "The server's certificate's expires #{peer_cert.not_after}"
5 changes: 3 additions & 2 deletions lib/httparty/fragment_with_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ module HTTParty
class FragmentWithResponse < SimpleDelegator
extend Forwardable

attr_reader :http_response
attr_reader :http_response, :connection

def code
@http_response.code.to_i
end

def initialize(fragment, http_response)
def initialize(fragment, http_response, connection)
@fragment = fragment
@http_response = http_response
@connection = connection
super fragment
end
end
Expand Down
5 changes: 3 additions & 2 deletions lib/httparty/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,16 @@ def perform(&block)
validate
setup_raw_request
chunked_body = nil
current_http = http

self.last_response = http.request(@raw_request) do |http_response|
self.last_response = current_http.request(@raw_request) do |http_response|
if block
chunks = []

http_response.read_body do |fragment|
encoded_fragment = encode_text(fragment, http_response['content-type'])
chunks << encoded_fragment if !options[:stream_body]
block.call FragmentWithResponse.new(encoded_fragment, http_response)
block.call FragmentWithResponse.new(encoded_fragment, http_response, current_http)
end

chunked_body = chunks.join
Expand Down
6 changes: 4 additions & 2 deletions spec/httparty/fragment_with_response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

RSpec.describe HTTParty::FragmentWithResponse do
it "access to fragment" do
fragment = HTTParty::FragmentWithResponse.new("chunk", nil)
fragment = HTTParty::FragmentWithResponse.new("chunk", nil, nil)
expect(fragment).to eq("chunk")
end
it "has access to delegators" do
response = double(code: '200')
fragment = HTTParty::FragmentWithResponse.new("chunk", response)
connection = double
fragment = HTTParty::FragmentWithResponse.new("chunk", response, connection)
expect(fragment.code).to eq(200)
expect(fragment.http_response).to eq response
expect(fragment.connection).to eq connection
end
end
12 changes: 10 additions & 2 deletions spec/httparty/ssl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
RSpec.describe HTTParty::Request do
context "SSL certificate verification" do
before do
WebMock.allow_net_connect!
WebMock.disable!
end

after do
WebMock.disable_net_connect!
WebMock.enable!
end

it "should fail when no trusted CA list is specified, by default" do
Expand Down Expand Up @@ -70,5 +70,13 @@
ssl_verify_test(:ssl_ca_path, ".", "bogushost.crt")
end.to raise_error(OpenSSL::SSL::SSLError)
end

it "should provide the certificate used by the server via peer_cert" do
peer_cert = nil
ssl_verify_test(:ssl_ca_file, "ca.crt", "server.crt") do |response|
peer_cert ||= response.connection.peer_cert
end
expect(peer_cert).to be_a OpenSSL::X509::Certificate
end
end
end
8 changes: 4 additions & 4 deletions spec/support/ssl_test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module HTTParty
module SSLTestHelper
def ssl_verify_test(mode, ca_basename, server_cert_filename, options = {})
def ssl_verify_test(mode, ca_basename, server_cert_filename, options = {}, &block)
options = {
format: :json,
timeout: 30
Expand All @@ -24,9 +24,9 @@ def ssl_verify_test(mode, ca_basename, server_cert_filename, options = {})
if mode
ca_path = File.expand_path("../../fixtures/ssl/generated/#{ca_basename}", __FILE__)
raise ArgumentError.new("#{ca_path} does not exist") unless File.exist?(ca_path)
return HTTParty.get("https://localhost:#{test_server.port}/", options)
return HTTParty.get("https://localhost:#{test_server.port}/", options, &block)
else
return HTTParty.get("https://localhost:#{test_server.port}/", options)
return HTTParty.get("https://localhost:#{test_server.port}/", options, &block)
end
ensure
test_server.stop if test_server
Expand All @@ -39,7 +39,7 @@ def ssl_verify_test(mode, ca_basename, server_cert_filename, options = {})

test_server.start

HTTParty.get("https://localhost:#{test_server.port}/", options)
HTTParty.get("https://localhost:#{test_server.port}/", options, &block)
ensure
test_server.stop if test_server
end
Expand Down

0 comments on commit 40204f2

Please sign in to comment.