From 25281b77dcd756458b106b9620adbab4bb31bdb8 Mon Sep 17 00:00:00 2001 From: Niklas Baumstark Date: Sat, 24 Sep 2011 23:55:18 +0200 Subject: [PATCH] add option to set an HTTP proxy --- lib/capybara/driver/webkit/browser.rb | 12 ++++ spec/browser_spec.rb | 86 +++++++++++++++++++++++++++ src/SetProxy.cpp | 24 ++++++++ src/SetProxy.h | 11 ++++ src/find_command.h | 2 + src/webkit_server.pro | 2 + 6 files changed, 137 insertions(+) create mode 100644 src/SetProxy.cpp create mode 100644 src/SetProxy.h diff --git a/lib/capybara/driver/webkit/browser.rb b/lib/capybara/driver/webkit/browser.rb index 3f58a72..5ae58ad 100644 --- a/lib/capybara/driver/webkit/browser.rb +++ b/lib/capybara/driver/webkit/browser.rb @@ -99,6 +99,18 @@ class Capybara::Driver::Webkit command("GetCookies").lines.map{ |line| line.strip }.select{ |line| !line.empty? } end + def set_proxy(opts = {}) + # remove proxy? + return command("SetProxy") if opts.empty? + + # set a HTTP proxy + command("SetProxy", + opts[:host] || "localhost", + opts[:port] || "0", + opts[:user] || "", + opts[:pass] || "") + end + private def start_server diff --git a/spec/browser_spec.rb b/spec/browser_spec.rb index 9bc081e..abf2411 100644 --- a/spec/browser_spec.rb +++ b/spec/browser_spec.rb @@ -2,6 +2,8 @@ require 'spec_helper' require 'self_signed_ssl_cert' require 'stringio' require 'capybara/driver/webkit/browser' +require 'socket' +require 'base64' describe Capybara::Driver::Webkit::Browser do @@ -88,4 +90,88 @@ describe Capybara::Driver::Webkit::Browser do end end + describe '#set_proxy' do + before do + @host = '127.0.0.1' + @user = 'user' + @pass = 'secret' + @url = "http://example.org/" + + serv = TCPServer.new(@host, 0) + @port = serv.addr[1] + + @proxy_requests = [] + @proxy = Thread.new(serv, @proxy_requests) do |serv, proxy_requests| + while conn = serv.accept do + # read request + request = [] + until (line = conn.readline.strip).empty? + request << line + end + + # send response + auth_header = request.find { |h| h =~ /Authorization:/i } + if auth_header || request[0].split(/\s+/)[1] =~ /^\// + 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 + proxy_requests << request if auth_header + else + conn.write "HTTP/1.1 407 Proxy Auth Required\r\n" + conn.write "Proxy-Authenticate: Basic realm=\"Proxy\"\r\n" + conn.write "\r\n" + conn.close + proxy_requests << request + end + end + end + + browser.set_proxy(:host => @host, + :port => @port, + :user => @user, + :pass => @pass) + browser.visit @url + @proxy_requests.size.should == 2 + @request = @proxy_requests[-1] + end + + after do + @proxy.kill + end + + it 'uses the HTTP proxy correctly' do + @request[0].should match /^GET\s+http:\/\/example.org\/\s+HTTP/i + @request.find { |header| + header =~ /^Host:\s+example.org$/i }.should_not be nil + end + + it 'sends correct proxy authentication' do + auth_header = @request.find { |header| + header =~ /^Proxy-Authorization:\s+/i } + auth_header.should_not be nil + + user, pass = Base64.decode64(auth_header.split(/\s+/)[-1]).split(":") + user.should == @user + pass.should == @pass + end + + it "uses the proxies' response" do + browser.body.should include "D'oh!" + end + + it 'uses original URL' do + browser.url.should == @url + end + + it 'is possible to disable proxy again' do + @proxy_requests.clear + browser.set_proxy + browser.visit "http://#{@host}:#{@port}/" + @proxy_requests.size.should == 0 + end + end end diff --git a/src/SetProxy.cpp b/src/SetProxy.cpp new file mode 100644 index 0000000..12742f2 --- /dev/null +++ b/src/SetProxy.cpp @@ -0,0 +1,24 @@ +#include "SetProxy.h" +#include "WebPage.h" +#include +#include + +SetProxy::SetProxy(WebPage *page, QObject *parent) + : Command(page, parent) +{ } + +void SetProxy::start(QStringList &arguments) +{ + // default to empty proxy + QNetworkProxy proxy; + + if (arguments.size() > 0) + proxy = QNetworkProxy(QNetworkProxy::HttpProxy, + arguments[0], + (quint16)(arguments[1].toInt()), + arguments[2], + arguments[3]); + + page()->networkAccessManager()->setProxy(proxy); + emit finished(new Response(true)); +} diff --git a/src/SetProxy.h b/src/SetProxy.h new file mode 100644 index 0000000..b9c154a --- /dev/null +++ b/src/SetProxy.h @@ -0,0 +1,11 @@ +#include "Command.h" + +class WebPage; + +class SetProxy : public Command { + Q_OBJECT; + + public: + SetProxy(WebPage *page, QObject *parent = 0); + virtual void start(QStringList &arguments); +}; diff --git a/src/find_command.h b/src/find_command.h index 4965719..3215c95 100644 --- a/src/find_command.h +++ b/src/find_command.h @@ -20,3 +20,5 @@ CHECK_COMMAND(Headers) CHECK_COMMAND(SetCookie) CHECK_COMMAND(ClearCookies) CHECK_COMMAND(GetCookies) +CHECK_COMMAND(Headers) +CHECK_COMMAND(SetProxy) diff --git a/src/webkit_server.pro b/src/webkit_server.pro index 9b02630..37e7b61 100644 --- a/src/webkit_server.pro +++ b/src/webkit_server.pro @@ -30,6 +30,7 @@ HEADERS = \ GetCookies.h \ CommandParser.h \ CommandFactory.h \ + SetProxy.h \ SOURCES = \ main.cpp \ @@ -61,6 +62,7 @@ SOURCES = \ GetCookies.cpp \ CommandParser.cpp \ CommandFactory.cpp \ + SetProxy.cpp \ RESOURCES = webkit_server.qrc QT += network webkit