diff --git a/lib/capybara/driver/webkit.rb b/lib/capybara/driver/webkit.rb index 97357b07..48373f5a 100644 --- a/lib/capybara/driver/webkit.rb +++ b/lib/capybara/driver/webkit.rb @@ -20,7 +20,8 @@ def initialize(app, options={}) @options = options @rack_server = Capybara::Server.new(@app) @rack_server.boot if Capybara.run_server - @browser = options[:browser] || Browser.new + @browser = options[:browser] || Browser.new( + :ignore_ssl_errors => options[:ignore_ssl_errors]) end def current_url diff --git a/lib/capybara/driver/webkit/browser.rb b/lib/capybara/driver/webkit/browser.rb index 1b23afa6..1a1ba6b2 100644 --- a/lib/capybara/driver/webkit/browser.rb +++ b/lib/capybara/driver/webkit/browser.rb @@ -12,6 +12,7 @@ def initialize(options = {}) @stdout = options.has_key?(:stdout) ? options[:stdout] : $stdout + @ignore_ssl_errors = options[:ignore_ssl_errors] start_server connect end @@ -126,7 +127,9 @@ def register_shutdown_hook end def server_pipe_and_pid(server_path) - pipe = IO.popen(server_path) + cmdline = [server_path] + cmdline << "--ignore-ssl-errors" if @ignore_ssl_errors + pipe = IO.popen(cmdline) [pipe, pipe.pid] end diff --git a/spec/browser_spec.rb b/spec/browser_spec.rb index 5cec8dae..f9b37541 100644 --- a/spec/browser_spec.rb +++ b/spec/browser_spec.rb @@ -1,10 +1,14 @@ require 'spec_helper' +require 'self_signed_ssl_cert' require 'stringio' require 'capybara/driver/webkit/browser' describe Capybara::Driver::Webkit::Browser do let(:browser) { Capybara::Driver::Webkit::Browser.new } + let(:browser_ignore_ssl_err) { + Capybara::Driver::Webkit::Browser.new(:ignore_ssl_errors => true) + } describe '#server_port' do subject { browser.server_port } @@ -32,6 +36,44 @@ io.string.should == "hello world\n" end + context 'handling of SSL validation errors' do + before do + # set up minimal HTTPS server + @host = "127.0.0.1" + serv = TCPServer.new(@host, 0) + @port = serv.addr[1] + + # set up SSL layer + serv = OpenSSL::SSL::SSLServer.new(serv, $openssl_self_signed_ctx) + + server_thread = Thread.new(serv) do |serv| + while conn = serv.accept do + # read request + request = [] + until (line = conn.readline.strip).empty? + request << line + end + + # write response + html = "D'oh!" + conn.write "HTTP/1.1 200 OK\r\n" + conn.write "Content-Type:text/html\r\n" + conn.write "Content-Length: %i\r\n" % html.size + conn.write "\r\n" + conn.write html + conn.close + end + end + end + + it "doesn't accepts a self-signed certificate by default" do + lambda { browser.visit "https://#{@host}:#{@port}/" }.should raise_error + end + + it 'accepts a self-signed certificate if configured to do so' do + browser_ignore_ssl_err.visit "https://#{@host}:#{@port}/" + end + end describe "forking" do it "only shuts down the server from the main process" do browser.reset! diff --git a/spec/self_signed_ssl_cert.rb b/spec/self_signed_ssl_cert.rb new file mode 100644 index 00000000..a07d48a5 --- /dev/null +++ b/spec/self_signed_ssl_cert.rb @@ -0,0 +1,42 @@ +require 'openssl' + +pem = <<-PEM_ENCODED +-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKW+grT6YW3gv79y +P9JkQDtm3cDSUhAhd/TEyRBt/pSKz3pNSygsleBJl2d7g8k0fteec95a7YnYRKGH +XhIpUOvl/3uaV2NVipqxwB+Z+0M+7HegxL3e4unaRFy9kf9/UXJzmuA9BTMLrm/w +IoW17f+dz7BIFZhCvRurkrmvzraNAgMBAAECgYBv4uB3bYJx20N16Jk+3OAjeXh/ +Hzu4me9Rc7pLdgVinyYaaK0wrJBsfSFRASdgnyh1RAjx9K3f3PfPlwMg/XUbA6Yd +YOYlMnBUwCJX09TH8RFFCzJzbBylpk/sTF1geICln2O2BloT2cM24PlEPvyz1xLa +XvxCOnJJfgNU1K6kvQJBANcEVyOMJ9RBfI8gj1o7S70J9yJRI4jvqxuvcOxJBCi6 +CDatkh/getHswsE3sLj25VhrNsi6UQcN8Bjm8Yjt8BsCQQDFVe0uCwobseprMOuW +dPU4+saN1cFnIT5Gp0iwYRPinjUlkh6H/AuUtUulKFXVmxk1KElpp1E3bxpCDgCp +oe53AkArO1Mt8Ys8kSIzQO+xy8RRsQRAoSHM8atsuJyy1YeBjM4D+GguApuPQ9Rw +tvrQZcv9OCleuJ98FKBW0XB1AKpLAkEAmOR3bJofDdAuWTjA/4TEzo32MsRwIZBv +KNzJg+bjOkzrzp1EzIVrD5/b6S20O1j9EeOR5as+UN3jEVS6DLQrBwJAe5OTrDiQ +vKtUaAwquC4f4Ia05KwJw+vFrPVaOqgc4QLdxRwx4PfV/Uw3OOqMolpPAvpUi9JI +LAwIaTtCvo18OQ== +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIICgDCCAemgAwIBAgIJANWcyeZB2ql1MA0GCSqGSIb3DQEBBQUAMFkxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xMTA5MjgyMDIx +MTFaFw0xMjA5MjcyMDIxMTFaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21l +LVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNV +BAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApb6CtPph +beC/v3I/0mRAO2bdwNJSECF39MTJEG3+lIrPek1LKCyV4EmXZ3uDyTR+155z3lrt +idhEoYdeEilQ6+X/e5pXY1WKmrHAH5n7Qz7sd6DEvd7i6dpEXL2R/39RcnOa4D0F +Mwuub/AihbXt/53PsEgVmEK9G6uSua/Oto0CAwEAAaNQME4wHQYDVR0OBBYEFBAm +x19zpY8M8FEcMXB4WQeUhqIiMB8GA1UdIwQYMBaAFBAmx19zpY8M8FEcMXB4WQeU +hqIiMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAcznCusWS5Ws77IUl +b87vdfCPVphICyfGHGWhHp3BZ3WLOphauAMdOYIiJGtPExyWr4DYpzbvx0+Ljg7G +2FNaI0QRXqbR5ccpvwm6KELmU0XDhykNaXiXSdnvIanr3z/hZ5e03mXAywo+nGQj +UYTVCb6g/uHVNzXq1NgHGuqogKY= +-----END CERTIFICATE----- +PEM_ENCODED + +$openssl_self_signed_key = key = OpenSSL::PKey::RSA.new(pem) +$openssl_self_signed_cert = cert = OpenSSL::X509::Certificate.new(pem) +$openssl_self_signed_ctx = ssl_ctx = OpenSSL::SSL::SSLContext.new +ssl_ctx.key = key +ssl_ctx.cert = cert