Thrift-1978: Ruby: Thrift should allow for the SSL verify mode to be set
Client: rb
Patch: Timur Alperovich

Ruby SSL verify mode cannot be specified, which means thrift cannot be used against servers with self-signed certificates over SSL. The suggested fix is to expose the SSL verification mode as a constructor argument in lib/rb/lib/thrift/transport/http_client_transport.rb.
diff --git a/lib/rb/lib/thrift/transport/http_client_transport.rb b/lib/rb/lib/thrift/transport/http_client_transport.rb
index 07f74bc..77ffe35 100644
--- a/lib/rb/lib/thrift/transport/http_client_transport.rb
+++ b/lib/rb/lib/thrift/transport/http_client_transport.rb
@@ -20,16 +20,18 @@
 
 require 'net/http'
 require 'net/https'
+require 'openssl'
 require 'uri'
 require 'stringio'
 
 module Thrift
   class HTTPClientTransport < BaseTransport
 
-    def initialize(url)
+    def initialize(url, opts = {})
       @url = URI url
       @headers = {'Content-Type' => 'application/x-thrift'}
       @outbuf = Bytes.empty_byte_buffer
+      @ssl_verify_mode = opts.fetch(:ssl_verify_mode, OpenSSL::SSL::VERIFY_PEER)
     end
 
     def open?; true end
@@ -43,6 +45,7 @@
     def flush
       http = Net::HTTP.new @url.host, @url.port
       http.use_ssl = @url.scheme == 'https'
+      http.verify_mode = @ssl_verify_mode if @url.scheme == 'https'
       resp = http.post(@url.request_uri, @outbuf, @headers)
       data = resp.body
       data = Bytes.force_binary_encoding(data)
diff --git a/lib/rb/spec/http_client_spec.rb b/lib/rb/spec/http_client_spec.rb
index 0890a8b..793fc73 100644
--- a/lib/rb/spec/http_client_spec.rb
+++ b/lib/rb/spec/http_client_spec.rb
@@ -68,4 +68,53 @@
       @client.flush
     end
   end
+
+  describe 'ssl enabled' do
+    before(:each) do
+      @service_path = "/path/to/service?param=value"
+      @server_uri = "https://my.domain.com"
+    end
+
+    it "should use SSL for https" do
+      client = Thrift::HTTPClientTransport.new("#{@server_uri}#{@service_path}")
+
+      client.write "test"
+
+      Net::HTTP.should_receive(:new).with("my.domain.com", 443).and_return do
+        mock("Net::HTTP").tap do |http|
+          http.should_receive(:use_ssl=).with(true)
+          http.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
+          http.should_receive(:post).with(@service_path, "test",
+              "Content-Type" => "application/x-thrift").and_return do
+            mock("Net::HTTPOK").tap do |response|
+              response.should_receive(:body).and_return "data"
+            end
+          end
+        end
+      end
+      client.flush
+      client.read(4).should == "data"
+    end
+
+    it "should set SSL verify mode when specified" do
+      client = Thrift::HTTPClientTransport.new("#{@server_uri}#{@service_path}",
+          :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE)
+
+      client.write "test"
+      Net::HTTP.should_receive(:new).with("my.domain.com", 443).and_return do
+        mock("Net::HTTP").tap do |http|
+          http.should_receive(:use_ssl=).with(true)
+          http.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
+          http.should_receive(:post).with(@service_path, "test",
+              "Content-Type" => "application/x-thrift").and_return do
+            mock("Net::HTTPOK").tap do |response|
+              response.should_receive(:body).and_return "data"
+            end
+          end
+        end
+      end
+      client.flush
+      client.read(4).should == "data"
+    end
+  end
 end