Skip to content
Browse files

Add functional tests.

Add simple Cucumber specs for right_http_connection

Add Cucumber specs for simple proxies.

Fill out SSL Cucumber specs.

Fix failures of CA stuff due to self signed certs.

Fix proxy SSL parsing.

Fix WEBrick's broken User-Agent parsing.
  • Loading branch information...
1 parent c6729d0 commit 79d01d163c025cbd8c1213a9b66d6411056f5a48 Graham Hughes committed Jan 31, 2011
View
8 .gitignore
@@ -1,3 +1,9 @@
*.sw?
*.DS_Store
-pkg/
+pkg/
+/spec/ca/01.pem
+/spec/ca/demoCA/index.txt.attr
+/spec/ca/demoCA/index.txt.old
+/spec/ca/demoCA/serial.old
+/spec/ca/server.crt
+/spec/ca/server.key
View
2 Gemfile
@@ -1 +1,3 @@
+source "http://rubygems.org"
+
gemspec
View
25 Gemfile.lock
@@ -4,12 +4,37 @@ PATH
right_http_connection (1.2.5)
GEM
+ remote: http://rubygems.org/
specs:
+ builder (3.0.0)
+ cucumber (0.10.0)
+ builder (>= 2.1.2)
+ diff-lcs (~> 1.1.2)
+ gherkin (~> 2.3.2)
+ json (~> 1.4.6)
+ term-ansicolor (~> 1.0.5)
+ diff-lcs (1.1.2)
+ flexmock (0.8.11)
+ gherkin (2.3.3)
+ json (~> 1.4.6)
+ json (1.4.6)
rake (0.8.7)
+ rspec (2.4.0)
+ rspec-core (~> 2.4.0)
+ rspec-expectations (~> 2.4.0)
+ rspec-mocks (~> 2.4.0)
+ rspec-core (2.4.0)
+ rspec-expectations (2.4.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.4.0)
+ term-ansicolor (1.0.5)
PLATFORMS
ruby
DEPENDENCIES
+ cucumber (~> 0.8)
+ flexmock (~> 0.8.11)
rake
right_http_connection!
+ rspec (~> 2.3)
View
28 Rakefile
@@ -8,6 +8,8 @@ require 'rake/packagetask'
require 'rake/gempackagetask'
require 'rake/rdoctask'
require 'rake/contrib/rubyforgepublisher'
+require 'rspec/core/rake_task'
+require 'cucumber/rake/task'
require 'fileutils'
include FileUtils
require File.join(File.dirname(__FILE__), 'lib', 'right_http_connection')
@@ -59,3 +61,29 @@ task :check_version do
exit
end
end
+
+task :default => 'spec'
+
+# == Unit Tests == #
+
+desc "Run unit tests"
+RSpec::Core::RakeTask.new
+
+namespace :spec do
+ desc "Run unit tests with RCov"
+ RSpec::Core::RakeTask.new(:rcov) do |t|
+ t.rcov = true
+ t.rcov_opts = %q[--exclude "spec"]
+ end
+
+ desc "Print Specdoc for unit tests"
+ RSpec::Core::RakeTask.new(:doc) do |t|
+ t.rspec_opts = ["--format", "documentation"]
+ end
+end
+
+# == Functional tests == #
+desc "Run functional tests"
+Cucumber::Rake::Task.new do |t|
+ t.cucumber_opts = %w{--color --format pretty}
+end
View
41 features/normal.feature
@@ -0,0 +1,41 @@
+Feature: RightHTTPConnection can connect to a web server
+ In order to access HTTP resources in a robust fashion
+ RightHTTPConnection users should be able to connect to a web server
+ And download data
+
+ Scenario: normal operation
+ Given a URL
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+
+ Scenario: normal operation with user agent
+ Given a URL
+ And the user agent "RightScale test"
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+ And the logs should show a "RightScale test" user agent
+
+ Scenario: read timeout
+ Given a URL that hangs intermittently
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL eventually
+
+ Scenario: open timeout
+ Given a URL whose server is unreliable
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL eventually
+
+ Scenario: consistent failure
+ Given a URL that fails all the time
+ When I request that URL using RightHTTPConnection
+ Then I should get an exception
+
+ Scenario: consistent read timeout
+ Given a URL that hangs all the time
+ When I request that URL using RightHTTPConnection
+ Then I should get an exception
+
+ Scenario: consistent open timeout
+ Given a URL whose server is listening but always down
+ When I request that URL using RightHTTPConnection
+ Then I should get an exception
View
60 features/proxy.feature
@@ -0,0 +1,60 @@
+Feature: RightHTTPConnection can connect to a web server through a proxy
+ In order to access HTTP resources through web proxies
+ RightHTTPConnection users should be able to connect to a web server proxy
+ And make connections from there
+
+ Scenario: normal operation
+ Given a URL
+ And a proxy
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+ And the proxy should have been used
+
+ Scenario: normal operation with username and password
+ Given a URL
+ And a proxy with a username and password
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+ And the proxy should have been used
+
+ Scenario: bad username and password
+ Given a URL
+ And a proxy with the wrong username and password
+ When I request that URL using RightHTTPConnection
+ Then I should get told to authenticate correctly
+
+ Scenario: intermittent failure
+ Given a URL that fails intermittently
+ And a proxy
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL eventually
+
+ Scenario: read timeout
+ Given a URL that hangs intermittently
+ And a proxy
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL eventually
+
+ Scenario: open timeout
+ Given a URL whose server is unreliable
+ And a proxy
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL eventually
+
+ Scenario: consistent failure
+ Given a URL that fails all the time
+ And a proxy
+ When I request that URL using RightHTTPConnection
+ Then I should get an exception
+
+ Scenario: consistent read timeout
+ Given a URL that hangs all the time
+ And a proxy
+ When I request that URL using RightHTTPConnection
+ Then I should get an exception
+
+ Scenario: consistent open timeout
+ Given a URL whose server is listening but always down
+ And a proxy
+ When I request that URL using RightHTTPConnection
+ Then I should get an exception
View
29 features/proxy_ssl.feature
@@ -0,0 +1,29 @@
+Feature: RightHTTPConnection can connect to a secure web server through a proxy
+ In order to access HTTP resources through web proxies in a secure robust fashion
+ RightHTTPConnection users should be able to connect to a web server proxy
+ And make connections to HTTPS servers from there
+
+ Scenario: normal operation
+ Given an HTTPS URL
+ And a proxy
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+ And the proxy should have been tunneled through
+
+ Scenario: normal operation with a CA certification file
+ Given an HTTPS URL
+ And a proxy
+ And a CA certification file containing that server
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+ And the proxy should have been tunneled through
+ And there should not be a warning about certificate verification failing
+
+ Scenario: man in the middle
+ Given an HTTPS URL
+ And a proxy
+ And a CA certification file not containing that server
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+ And there should be a warning about certificate verification failing
+ And the proxy should have been tunneled through
View
23 features/ssl.feature
@@ -0,0 +1,23 @@
+Feature: RightHTTPConnection can connect to a secure web server
+ In order to access HTTP resources in a secure robust fashion
+ RightHTTPConnection users should be able to connect to a web server that uses HTTPS
+ And download data
+
+ Scenario: normal operation
+ Given an HTTPS URL
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+
+ Scenario: normal operation with a CA certification file
+ Given an HTTPS URL
+ And a CA certification file containing that server
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+ And there should not be a warning about certificate verification failing
+
+ Scenario: man in the middle
+ Given an HTTPS URL
+ And a CA certification file not containing that server
+ When I request that URL using RightHTTPConnection
+ Then I should get the contents of the URL
+ And there should be a warning about certificate verification failing
View
34 features/step_definitions/logs.rb
@@ -0,0 +1,34 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+Then /^the logs should show a \"([^\"]*)\" user agent$/ do |ua|
+ File.open("#{@tmpdir}/weblog.out").read.should =~ /\Alocalhost - - \[[^\]]*\] \"GET [^ ]+ HTTP\/1\.1\" \d+ \d+ \"-\" \"#{Regexp.escape(ua)}\"\n\Z/
+end
+
+Then /^the proxy should have been used$/ do
+ File.open("#{@tmpdir}/proxy.out").read.should =~ /\Alocalhost - [^ ]+ \[[^\]]*\] \"GET #{Regexp.escape(@uri.to_s)} HTTP\/1\.1\" \d+ \d+ \"-\" \".*\"\n\Z/
+end
+
+Then /^the proxy should have been tunneled through$/ do
+ File.open("#{@tmpdir}/proxy.out").read.should =~ /\Alocalhost - [^ ]+ \[[^\]]*\] \"CONNECT #{Regexp.escape(@uri.host)}:#{Regexp.escape(@uri.port.to_s)} HTTP\/1\.1\" \d+ \d+ \"-\" \".*\"\n\Z/
+end
View
60 features/step_definitions/proxy.rb
@@ -0,0 +1,60 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+Given /^a proxy$/ do
+ @subprocess_pids << fork do
+ ENV['RACK_ENV'] = "test"
+ Dir.chdir(@tmpdir)
+ STDIN.close
+ output = File.open("#{@tmpdir}/proxy.out", "w")
+ STDOUT.reopen(output)
+ exec "ruby", File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/proxy_server.rb"))
+ end
+ Given "a server listening on port 9090"
+ @proxy_host = "localhost"
+ @proxy_port = "9090"
+end
+
+Given /^a proxy with a username and password$/ do
+ @subprocess_pids << fork do
+ ENV['RACK_ENV'] = "test"
+ Dir.chdir(@tmpdir)
+ STDIN.close
+ output = File.open("#{@tmpdir}/proxy.out", "w")
+ STDOUT.reopen(output)
+ exec "ruby", File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/proxy_server.rb")), "username", "password"
+ end
+ Given "a server listening on port 9090"
+ @proxy_host = "localhost"
+ @proxy_port = "9090"
+ @proxy_username = "username"
+ @proxy_password = "password"
+end
+
+Given /^a proxy with the wrong username and password$/ do
+ Given "a proxy with a username and password"
+ @proxy_username = "wrong_username"
+ @proxy_password = "wrong_password"
+end
View
89 features/step_definitions/right_http_connection.rb
@@ -0,0 +1,89 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+class RightHttpConnectionFailure < Exception
+end
+
+Given /^a captive logger$/ do
+ @output = StringIO.new("", "w")
+ @logger = Logger.new(@output)
+end
+
+Given /^the user agent \"([^\"]*)\"$/ do |ua|
+ @user_agent = ua
+end
+
+When /^I request that URL using RightHTTPConnection$/ do
+ Given "a captive logger"
+ hash = {:logger => @logger, :exception => RightHttpConnectionFailure}
+ hash[:user_agent] = @user_agent if @user_agent
+ hash[:ca_file] = @ca_file if @ca_file
+ hash[:proxy_host] = @proxy_host if @proxy_host
+ hash[:proxy_port] = @proxy_port if @proxy_port
+ hash[:proxy_username] = @proxy_username if @proxy_username
+ hash[:proxy_password] = @proxy_password if @proxy_password
+ @connection = Rightscale::HttpConnection.new(hash)
+ @request = Net::HTTP::Get.new(@uri.request_uri)
+ @request["Host"] = "#{@uri.host}:#{@uri.port}"
+ begin
+ @result = @connection.request(:server => @uri.host, :port => @uri.port,
+ :protocol => @uri.scheme, :request => @request)
+ rescue RightHttpConnectionFailure => e
+ @result = nil
+ @exception = e
+ end
+end
+
+RSpec::Matchers.define :have_no_errors_in do |logs|
+ match do |connection|
+ logs !~ /Rightscale::HttpConnection : request failure count: \d+, exception: .*$/
+ end
+ failure_message_for_should do |connection|
+ "should have no errors, but saw one in the logs, which are as follows: #{logs}"
+ end
+ failure_message_for_should_not do |connection|
+ "should have seen some kind of errors in the logs, but none occurred; logs are: #{logs}"
+ end
+end
+
+Then /^I should get the contents of the URL$/ do
+ @result.should be_kind_of(Net::HTTPSuccess)
+ @result.body.should == @expected_contents
+ @connection.should have_no_errors_in(@output.string)
+end
+
+Then /^I should get the contents of the URL eventually$/ do
+ @result.should be_kind_of(Net::HTTPSuccess)
+ @result.body.should == @expected_contents
+ @connection.should_not have_no_errors_in(@output.string)
+end
+
+Then /^I should get an exception$/ do
+ @result.should be_nil
+ @exception.should_not be_nil
+end
+
+Then /^I should get told to authenticate correctly$/ do
+ @result.should be_kind_of(Net::HTTPProxyAuthenticationRequired)
+ @connection.should have_no_errors_in(@output.string)
+end
View
44 features/step_definitions/ssl.rb
@@ -0,0 +1,44 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+Given /^an HTTPS URL$/ do
+ Given "a really dumb SSL enabled web server"
+ @uri = URI.parse("https://127.0.0.1:7890/good")
+ @expected_contents = "good"
+end
+
+Given /^a CA certification file containing that server$/ do
+ @ca_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec", "good.ca"))
+end
+
+Given /^a CA certification file not containing that server$/ do
+ @ca_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec", "bad.ca"))
+end
+
+Then /^there should be a warning about certificate verification failing$/ do
+ @output.string.should =~ /.*WARN -- : ##### 127\.0\.0\.1 certificate verify failed:.*/
+end
+
+Then /^there should not be a warning about certificate verification failing$/ do
+ @output.string.should_not =~ /.*WARN -- : ##### 127\.0\.0\.1 certificate verify failed:.*/
+end
View
90 features/step_definitions/web_server.rb
@@ -0,0 +1,90 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+Given /^a really dumb web server$/ do
+ @subprocess_pids << fork do
+ ENV['RACK_ENV'] = "test"
+ Dir.chdir(@tmpdir)
+ STDIN.close
+ output = File.open("#{@tmpdir}/weblog.out", "w")
+ STDOUT.reopen(output)
+ exec "ruby", File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/really_dumb_webserver.rb"))
+ end
+ Given "a server listening on port 7890"
+end
+
+Given /^a really dumb SSL enabled web server$/ do
+ @subprocess_pids << fork do
+ ENV['RACK_ENV'] = "test"
+ Dir.chdir(@tmpdir)
+ STDIN.close
+ output = File.open("#{@tmpdir}/weblog.out", "w")
+ STDOUT.reopen(output)
+ exec("ruby",
+ File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/really_dumb_webserver.rb")),
+ File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/server.crt")),
+ File.expand_path(File.join(File.dirname(__FILE__), "..", "..",
+ "spec/server.key")))
+ end
+ Given "a server listening on port 7890"
+end
+
+Given /^a URL$/ do
+ Given "a really dumb web server"
+ @uri = URI.parse("http://127.0.0.1:7890/good")
+ @expected_contents = "good"
+end
+
+Given /^a URL that hangs intermittently$/ do
+ Given "a really dumb web server"
+ Rightscale::HttpConnection.params[:http_connection_read_timeout] = 2
+ @uri = URI.parse("http://127.0.0.1:7890/intermittent-hang")
+ @expected_contents = "good"
+end
+
+Given /^a URL that hangs all the time$/ do
+ Given "a really dumb web server"
+ Rightscale::HttpConnection.params[:http_connection_read_timeout] = 2
+ @uri = URI.parse("http://127.0.0.1:7890/hang")
+ @expected_contents = "irrelevant"
+end
+
+Given /^a URL that fails intermittently$/ do
+ pending "this seems to require custom server code"
+end
+
+Given /^a URL whose server is unreliable$/ do
+ pending "this seems to require custom server code"
+end
+
+Given /^a URL that fails all the time$/ do
+ pending "this seems to require custom server code"
+end
+
+Given /^a URL whose server is listening but always down$/ do
+ pending "this seems to require custom server code"
+end
+
View
32 features/support/env.rb
@@ -0,0 +1,32 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+require 'rubygems'
+require 'bundler/setup'
+$LOAD_PATH << File.expand_path('../../../lib', __FILE__)
+require 'right_http_connection'
+require 'uri'
+require 'tmpdir'
+require 'socket'
+require 'stringio'
+require 'logger'
View
30 features/support/hooks.rb
@@ -0,0 +1,30 @@
+#--
+# Copyright: Copyright (c) 2010 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+Before do
+ @tmpdir = Dir.mktmpdir
+end
+
+After do
+ FileUtils.remove_entry_secure @tmpdir
+end
View
47 features/support/subprocesses.rb
@@ -0,0 +1,47 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+Before do
+ @subprocess_pids = []
+end
+
+# Kill running reposes after test finishes.
+After do
+ @subprocess_pids.each do |pid|
+ Process.kill(:TERM, pid)
+ Process.waitpid(pid)
+ end
+end
+
+Given /^a server listening on port (\d+)$/ do |port|
+ portnumber = port.to_i
+ loop do
+ begin
+ s = TCPSocket.open('127.0.0.1', portnumber)
+ s.close
+ break
+ rescue SystemCallError
+ sleep 0.1
+ end
+ end
+end
View
3 right_http_connection.gemspec
@@ -41,6 +41,9 @@ Gem::Specification.new do |spec|
spec.require_path = 'lib'
spec.add_development_dependency('rake')
+ spec.add_development_dependency('rspec', "~> 2.3")
+ spec.add_development_dependency('cucumber', "~> 0.8")
+ spec.add_development_dependency('flexmock', "~> 0.8.11")
spec.description = <<-EOF
Rightscale::HttpConnection is a robust HTTP/S library. It implements a retry
View
2,794 spec/bad.ca
2,794 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
64 spec/ca/Rakefile
@@ -0,0 +1,64 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+require 'rubygems'
+require 'rake'
+require 'rake/clean'
+
+file "passphrase.txt" do
+ File.open("passphrase.txt", "w") { |f| f.puts "foobar" }
+end
+
+file "ca.key" => "passphrase.txt" do |t|
+ sh("openssl", "req", "-new", "-x509", "-extensions", "v3_ca",
+ "-keyout", "ca.key", "-out", "ca.crt", "-days", "1825",
+ "-passout", "file:#{t.prerequisites[0]}")
+end
+
+file "ca.crt" => "ca.key"
+
+file "server.key" do |t|
+ sh("openssl", "req", "-new", "-nodes", "-keyout", t.name,
+ "-out", "server.csr", "-days", "365")
+end
+file "server.csr" => "server.key"
+
+directory "demoCA"
+file "demoCA/index.txt" => "demoCA" do
+ sh "touch", "demoCA/index.txt"
+end
+file "demoCA/serial" => "demoCA" do
+ File.open("demoCA/serial", "w") {|f| f.puts "01"}
+end
+
+file "server.crt" => ["server.csr", "ca.key", "passphrase.txt", "demoCA/index.txt", "demoCA/serial"] do |t|
+ sh("openssl", "ca", "-policy", "policy_anything", "-out", t.name,
+ "-outdir", ".",
+ "-cert", "ca.crt", "-keyfile", "ca.key", "-passin", "file:passphrase.txt",
+ "-infiles", "server.csr")
+end
+
+task :default => ["ca.crt", "server.crt", "server.key"] do |t|
+ sh("cp", *(t.prerequisites + [".."]))
+ sh "cp", "ca.crt", "../good.ca"
+end
View
23 spec/ca/ca.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID6TCCA1KgAwIBAgIJAMbnbxA3pDCfMA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FudGEgQmFy
+YmFyYTEZMBcGA1UEChMQUmlnaHRTY2FsZSwgSW5jLjEVMBMGA1UECxMMQXp1cmUg
+U3ByaW50MRYwFAYDVQQDEw1BenVyZSB0ZXN0IENBMSQwIgYJKoZIhvcNAQkBFhVn
+cmFoYW1AcmlnaHRzY2FsZS5jb20wHhcNMTEwMjAxMDIzNjU2WhcNMTYwMTMxMDIz
+NjU2WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV
+BAcTDVNhbnRhIEJhcmJhcmExGTAXBgNVBAoTEFJpZ2h0U2NhbGUsIEluYy4xFTAT
+BgNVBAsTDEF6dXJlIFNwcmludDEWMBQGA1UEAxMNQXp1cmUgdGVzdCBDQTEkMCIG
+CSqGSIb3DQEJARYVZ3JhaGFtQHJpZ2h0c2NhbGUuY29tMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDha7yTsOMojuy/4RvZqPlPNxQj2AAhEIFONvMcSTXBwlND
+xtOXHzF963LxBrxqOXnCMvfSBnzsfywS6k8dGwBpxoiG420QK6SZ0X3DEwzBXVX7
+jnxQICtMzFO/h/AYhuNbzeAPwzrnRKNhqJGLuKOKga7Z6+ZyyXtKIf2+apjO+wID
+AQABo4IBEzCCAQ8wHQYDVR0OBBYEFL4IVWcPJhd11ajwbIT2va3O5XhpMIHfBgNV
+HSMEgdcwgdSAFL4IVWcPJhd11ajwbIT2va3O5XhpoYGwpIGtMIGqMQswCQYDVQQG
+EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FudGEgQmFyYmFy
+YTEZMBcGA1UEChMQUmlnaHRTY2FsZSwgSW5jLjEVMBMGA1UECxMMQXp1cmUgU3By
+aW50MRYwFAYDVQQDEw1BenVyZSB0ZXN0IENBMSQwIgYJKoZIhvcNAQkBFhVncmFo
+YW1AcmlnaHRzY2FsZS5jb22CCQDG528QN6QwnzAMBgNVHRMEBTADAQH/MA0GCSqG
+SIb3DQEBBQUAA4GBADbJoPLdHiwR3RQ9mrKUgxdCv14BLvg1UAP6QhU1Y8TIUxAp
+HljbEHYk/B9PoG9GsdxTlnFu7LJVOZB7c+aFOaMyRR4TUUwPm/AGMMFnZMbnecqD
+Y9JV2y0mn10i6er9Lz19CGi9TlOUuNdYKLT9cTCaqaVFPvXk44sNb3/5mrpi
+-----END CERTIFICATE-----
View
18 spec/ca/ca.key
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,269408AD40EA6D81
+
+u6a+jexScTHmtbYnNUSvhxJgpXVN9e/ctKYKBm27qlFraLz+Vnkj0fMW8yHzY+We
+8517Kl82vytZhTjnU6Elw6RpfgJzs0TnP5OhvLBsmNEXpHymNCcGt7p8jJopHEaa
+8IT87WqKqryyEjbkEFqCb0QfwLBd9PVT+lQeEcPAHlMkC8lwkjVCAsvJaZ3GsURJ
+Tb5xHOYj0jccm/xrg82e/25emMqTGCBKwb7cTyyKxmL8ezi1vA9jJcf9M7KgNgUA
+FGo7mrCK9niHfOLULD8f3WN+2DHoTwIDXseNWS/giSePQZZupVmWEUtDkt2x9qCb
+nJat/ESncAU1BrqXiYTpdtgao/TXcpt+7w/DMLHbOxus7p9sqZnAcXc/0Y+ZsYF1
+rq0spVpgJfDU6sP0ay61rOf7YnTko0oewiF0/c+dB42XErkM88wupNHJfr+M2Cfg
+w8BQeCx1l14W2haWlTgstBhfGWod76CT7Ng7/927L7P3pJ5ebS7qWRMskJGFMCFV
+9rd7OjGiYEqB365YI0VUiZPkXE9bXxRyfnU6K7hVtR3kY+TYADEgcaDE+6W1bgOc
+jwEeObdDqRbAR/YD/3myhvRF9k7C/fQ5PqOC3dlQZTXQCAJYCt9aNXkxBnMmh1WS
+GDDUpF9s6lSoUFm+yic4RXNX9Jj5npUKZR1TBqZfHQjzRLxEKxQo6VESa5QEWkM0
+C2Rsmxs/3dXXTJTOrP9rzWhQmxdCz7n4efHEHuMuVXvRtEAFjMrKfcH1t5fFQ8fA
+sBrulv26/ygJFwZrSfq7ILW/AcYFEMmQflLGoVJ8aiSl4oBwIS7FvA==
+-----END RSA PRIVATE KEY-----
View
1 spec/ca/demoCA/index.txt
@@ -0,0 +1 @@
+V 120201024841Z 01 unknown /C=US/ST=California/L=Santa Barbara/O=RightScale, Inc./OU=Azure Sprint/CN=127.0.0.1
View
1 spec/ca/demoCA/serial
@@ -0,0 +1 @@
+02
View
1 spec/ca/passphrase.txt
@@ -0,0 +1 @@
+foobar
View
12 spec/ca/server.csr
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBwTCCASoCAQAwgYAxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
+MRYwFAYDVQQHEw1TYW50YSBCYXJiYXJhMRkwFwYDVQQKExBSaWdodFNjYWxlLCBJ
+bmMuMRUwEwYDVQQLEwxBenVyZSBTcHJpbnQxEjAQBgNVBAMTCTEyNy4wLjAuMTCB
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvgzuf4/JyaNK3VC7eijUk0uCtJ6H
+WInYzgrpX/Xxmf0Po6nZ6RlY4YiPL9YtqaPLXuT+GDkDDsOMAZDBFsPbiiiZM4QT
+qW8e1hiM8xg6w/wrf/ofBakjTsik3Oa0kIWCs1cymLsEZJMJsoH9CpoDGUvA47AB
+QVkSq00F6IAF0r8CAwEAAaAAMA0GCSqGSIb3DQEBBQUAA4GBADiV9fCKFAiA9k98
+cgHpVKpLpSGkGXndwyOZO+E0H7rwTtNwW3DM0CKN7z0EpbE4YBtSF+3qOFV2zWJF
+N3dWd2bJWDwfLybtHXWIADKmUXjkoGJfGNoh+APMqNtRLudAXIoDkiJRmBgFizTV
+mA9goBMk2IGpUmMVl778iGD6rBQh
+-----END CERTIFICATE REQUEST-----
View
23 spec/good.ca
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID6TCCA1KgAwIBAgIJAMbnbxA3pDCfMA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FudGEgQmFy
+YmFyYTEZMBcGA1UEChMQUmlnaHRTY2FsZSwgSW5jLjEVMBMGA1UECxMMQXp1cmUg
+U3ByaW50MRYwFAYDVQQDEw1BenVyZSB0ZXN0IENBMSQwIgYJKoZIhvcNAQkBFhVn
+cmFoYW1AcmlnaHRzY2FsZS5jb20wHhcNMTEwMjAxMDIzNjU2WhcNMTYwMTMxMDIz
+NjU2WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV
+BAcTDVNhbnRhIEJhcmJhcmExGTAXBgNVBAoTEFJpZ2h0U2NhbGUsIEluYy4xFTAT
+BgNVBAsTDEF6dXJlIFNwcmludDEWMBQGA1UEAxMNQXp1cmUgdGVzdCBDQTEkMCIG
+CSqGSIb3DQEJARYVZ3JhaGFtQHJpZ2h0c2NhbGUuY29tMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDha7yTsOMojuy/4RvZqPlPNxQj2AAhEIFONvMcSTXBwlND
+xtOXHzF963LxBrxqOXnCMvfSBnzsfywS6k8dGwBpxoiG420QK6SZ0X3DEwzBXVX7
+jnxQICtMzFO/h/AYhuNbzeAPwzrnRKNhqJGLuKOKga7Z6+ZyyXtKIf2+apjO+wID
+AQABo4IBEzCCAQ8wHQYDVR0OBBYEFL4IVWcPJhd11ajwbIT2va3O5XhpMIHfBgNV
+HSMEgdcwgdSAFL4IVWcPJhd11ajwbIT2va3O5XhpoYGwpIGtMIGqMQswCQYDVQQG
+EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FudGEgQmFyYmFy
+YTEZMBcGA1UEChMQUmlnaHRTY2FsZSwgSW5jLjEVMBMGA1UECxMMQXp1cmUgU3By
+aW50MRYwFAYDVQQDEw1BenVyZSB0ZXN0IENBMSQwIgYJKoZIhvcNAQkBFhVncmFo
+YW1AcmlnaHRzY2FsZS5jb22CCQDG528QN6QwnzAMBgNVHRMEBTADAQH/MA0GCSqG
+SIb3DQEBBQUAA4GBADbJoPLdHiwR3RQ9mrKUgxdCv14BLvg1UAP6QhU1Y8TIUxAp
+HljbEHYk/B9PoG9GsdxTlnFu7LJVOZB7c+aFOaMyRR4TUUwPm/AGMMFnZMbnecqD
+Y9JV2y0mn10i6er9Lz19CGi9TlOUuNdYKLT9cTCaqaVFPvXk44sNb3/5mrpi
+-----END CERTIFICATE-----
View
57 spec/proxy_server.rb
@@ -0,0 +1,57 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+# A HttpWatch proxy clone (without the license!)
+require 'rubygems'
+require 'webrick/httpproxy'
+require 'webrick/httpauth'
+require 'cgi'
+
+# Patch broken WEBrick escape
+module WEBrick::HTMLUtils
+ def escape(string)
+ CGI.escapeHTML(string.to_s)
+ end
+ module_function :escape
+end
+
+username, password = ARGV[0], ARGV[1]
+
+logger = WEBrick::Log.new($stderr, WEBrick::Log::WARN)
+config = {}
+config[:Port] = 9090
+config[:Logger] = logger
+config[:AccessLog] = [[$stdout, WEBrick::AccessLog::COMBINED_LOG_FORMAT]]
+unless username.nil? || password.nil?
+ config[:ProxyAuthProc] = Proc.new do |req, res|
+ WEBrick::HTTPAuth.proxy_basic_auth(req, res, "Test realm") {|user, pass|
+ user == username && pass == password
+ }
+ end
+end
+$stdout.sync = true
+server = WEBrick::HTTPProxyServer.new(config)
+['INT', 'TERM'].each {|signal|
+ trap(signal) { server.shutdown }
+}
+server.start
View
113 spec/really_dumb_webserver.rb
@@ -0,0 +1,113 @@
+#-- -*- mode: ruby; encoding: utf-8 -*-
+# Copyright: Copyright (c) 2011 RightScale, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# 'Software'), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+require 'webrick'
+
+ssl_cert, ssl_key = ARGV[0], ARGV[1]
+
+# Monkey patch bad User-Agent parsing
+module WEBrick::AccessLog
+ module_function
+
+ def format(format_string, params)
+ format_string.gsub(/\%(?:\{(.*?)\})?>?([a-zA-Z%])/){
+ param, spec = $1, $2
+ case spec[0]
+ when ?e, ?i, ?n, ?o
+ raise AccessLogError,
+ "parameter is required for \"#{spec}\"" unless param
+ if params[spec][param]
+ escape(params[spec][param])
+ else
+ "-"
+ end
+ when ?t
+ params[spec].strftime(param || CLF_TIME_FORMAT)
+ when ?%
+ "%"
+ else
+ escape(params[spec].to_s)
+ end
+ }
+ end
+end
+
+logger = WEBrick::Log.new($stderr, WEBrick::Log::WARN)
+config = {}
+config[:Port] = 7890
+config[:Logger] = logger
+config[:AccessLog] = [[$stdout, WEBrick::AccessLog::COMBINED_LOG_FORMAT]]
+unless ssl_cert.nil? || ssl_key.nil?
+ require 'webrick/https'
+ config[:SSLEnable] = true
+ config[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_NONE
+ config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.open(ssl_key).read)
+ config[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.open(ssl_cert).read)
+ config[:SSLCertName] = [["CN", "Graham Hughes"]]
+end
+$stdout.sync = true
+server = WEBrick::HTTPServer.new(config)
+
+server.mount_proc('/good') {|req, resp|
+ resp.status = 200
+ resp['Content-Type'] = "text/plain"
+ resp.body = "good"
+}
+intermittent_times = 0
+server.mount_proc('/intermittent-hang') {|req, resp|
+ intermittent_times += 1
+ if intermittent_times % 2 == 1
+ sleep 5
+ resp.status = 403
+ resp['Content-Type'] = "text/plain"
+ resp.body = "bad"
+ else
+ resp.status = 200
+ resp['Content-Type'] = "text/plain"
+ resp.body = "good"
+ end
+}
+server.mount_proc('/hang') {|req, resp|
+ sleep 5
+ resp.status = 200
+ resp['Content-Type'] = "text/plain"
+ resp.body = "good"
+}
+server.mount_proc('/ugly') {|req, resp|
+ resp.status = 404
+ resp['Content-Type'] = "text/plain"
+ resp.body = "ugly"
+}
+server.mount_proc('/filename') {|req, resp|
+ resp.status = 200
+ resp['ETag'] = File.stat('filename').mtime
+ resp['Content-Type'] = "text/plain"
+ resp.body = File.open("filename").read
+}
+
+# trap signals to invoke shutdown cleanly
+['INT', 'TERM'].each { |signal|
+ trap(signal) { server.shutdown }
+}
+
+server.start
View
62 spec/server.crt
@@ -0,0 +1,62 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=California, L=Santa Barbara, O=RightScale, Inc., OU=Azure Sprint, CN=Azure test CA/emailAddress=graham@rightscale.com
+ Validity
+ Not Before: Feb 1 02:48:41 2011 GMT
+ Not After : Feb 1 02:48:41 2012 GMT
+ Subject: C=US, ST=California, L=Santa Barbara, O=RightScale, Inc., OU=Azure Sprint, CN=127.0.0.1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:be:0c:ee:7f:8f:c9:c9:a3:4a:dd:50:bb:7a:28:
+ d4:93:4b:82:b4:9e:87:58:89:d8:ce:0a:e9:5f:f5:
+ f1:99:fd:0f:a3:a9:d9:e9:19:58:e1:88:8f:2f:d6:
+ 2d:a9:a3:cb:5e:e4:fe:18:39:03:0e:c3:8c:01:90:
+ c1:16:c3:db:8a:28:99:33:84:13:a9:6f:1e:d6:18:
+ 8c:f3:18:3a:c3:fc:2b:7f:fa:1f:05:a9:23:4e:c8:
+ a4:dc:e6:b4:90:85:82:b3:57:32:98:bb:04:64:93:
+ 09:b2:81:fd:0a:9a:03:19:4b:c0:e3:b0:01:41:59:
+ 12:ab:4d:05:e8:80:05:d2:bf
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 53:2D:31:08:5D:F7:AC:1F:0B:05:68:9D:02:16:EE:A8:95:58:B3:B7
+ X509v3 Authority Key Identifier:
+ keyid:BE:08:55:67:0F:26:17:75:D5:A8:F0:6C:84:F6:BD:AD:CE:E5:78:69
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 24:7e:c8:da:b9:bb:f8:ab:49:cb:cc:58:39:51:eb:e4:70:0f:
+ 1c:18:19:f3:91:54:9e:7a:9f:9b:9b:02:e2:83:81:6f:0b:c6:
+ d6:15:e7:22:f3:0b:72:01:fa:d2:1a:f9:17:57:15:aa:fb:f6:
+ 1f:d2:9d:ef:45:23:58:66:38:c1:ad:f0:c9:9e:c0:d7:7c:17:
+ f1:1e:f9:6b:bd:52:48:8b:ac:80:89:41:35:10:d4:a1:c8:68:
+ 6e:87:e7:18:45:31:ff:35:a7:57:07:c1:aa:54:75:b2:78:f2:
+ 3d:7d:33:38:7f:71:4a:4f:ee:ed:d8:ca:cb:f3:8e:01:41:44:
+ 2a:3f
+-----BEGIN CERTIFICATE-----
+MIIDHTCCAoagAwIBAgIBATANBgkqhkiG9w0BAQUFADCBqjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbnRhIEJhcmJhcmExGTAX
+BgNVBAoTEFJpZ2h0U2NhbGUsIEluYy4xFTATBgNVBAsTDEF6dXJlIFNwcmludDEW
+MBQGA1UEAxMNQXp1cmUgdGVzdCBDQTEkMCIGCSqGSIb3DQEJARYVZ3JhaGFtQHJp
+Z2h0c2NhbGUuY29tMB4XDTExMDIwMTAyNDg0MVoXDTEyMDIwMTAyNDg0MVowgYAx
+CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW50
+YSBCYXJiYXJhMRkwFwYDVQQKExBSaWdodFNjYWxlLCBJbmMuMRUwEwYDVQQLEwxB
+enVyZSBTcHJpbnQxEjAQBgNVBAMTCTEyNy4wLjAuMTCBnzANBgkqhkiG9w0BAQEF
+AAOBjQAwgYkCgYEAvgzuf4/JyaNK3VC7eijUk0uCtJ6HWInYzgrpX/Xxmf0Po6nZ
+6RlY4YiPL9YtqaPLXuT+GDkDDsOMAZDBFsPbiiiZM4QTqW8e1hiM8xg6w/wrf/of
+BakjTsik3Oa0kIWCs1cymLsEZJMJsoH9CpoDGUvA47ABQVkSq00F6IAF0r8CAwEA
+AaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0
+ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFMtMQhd96wfCwVonQIW7qiVWLO3MB8G
+A1UdIwQYMBaAFL4IVWcPJhd11ajwbIT2va3O5XhpMA0GCSqGSIb3DQEBBQUAA4GB
+ACR+yNq5u/irScvMWDlR6+RwDxwYGfORVJ56n5ubAuKDgW8LxtYV5yLzC3IB+tIa
++RdXFar79h/Sne9FI1hmOMGt8MmewNd8F/Ee+Wu9UkiLrICJQTUQ1KHIaG6H5xhF
+Mf81p1cHwapUdbJ48j19Mzh/cUpP7u3YysvzjgFBRCo/
+-----END CERTIFICATE-----
View
15 spec/server.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQC+DO5/j8nJo0rdULt6KNSTS4K0nodYidjOCulf9fGZ/Q+jqdnp
+GVjhiI8v1i2po8te5P4YOQMOw4wBkMEWw9uKKJkzhBOpbx7WGIzzGDrD/Ct/+h8F
+qSNOyKTc5rSQhYKzVzKYuwRkkwmygf0KmgMZS8DjsAFBWRKrTQXogAXSvwIDAQAB
+AoGBAIb2zgRey3FbelXy+ECHcHbt3/N+xSU2N3YTP6p7EUlG8m1KuMqVyo3Xmb/h
+/OmEvW81ddEj46z/Z5TRBJ6zFlssmo0xYkbYfjXBbqumn7D8XA8ogFLWwDQzrIvQ
+c2iRuiitXiocqFSVw6NaU7YUfURFCepech9yu0kEkeO2dolJAkEA4gnjJmv7b1D8
+GsZhj+q31vfpfqd/PHOS22IhSQ9Q7xN3uqsH5sDnPWcuwl3z9rcmJYe3wcvgJRkZ
+Dl+t2oNOdQJBANc93maaDbnlydf+5h+aT+wqkzp4U4iE1fNRcbBRjWF+UY4+3NYe
+0PVf15UNcXjzo+KSQupLgN7Py9BkTFhkHeMCQDpcZSqxbKzUExNyrxPyfV7iiYXr
+Bz37dSpxjriHXNUtiJdIu3SHz+yZrIgArBHCPfYosXg3BHtvnHmKmJ+3kVUCQFEF
+E9sxL+uCyKiKZVsN/fmayRKgSmk//zz4sj+5YuuI3fAaT4w1y1ghvId5qPXrWAwo
+HBIPW7IDK+gEaQx4mxsCQQCpuseeUqAuZXlzedbff5KBq0RcrzzEgRZCGyDM/uPU
+boj87H/49H68OZmPzER+hHTbo5pYSOI3A9v5XmOOORxb
+-----END RSA PRIVATE KEY-----

0 comments on commit 79d01d1

Please sign in to comment.
Something went wrong with that request. Please try again.