diff options
author | Steve Kemp <steve@steve.org.uk> | 2012-11-23 21:49:24 +0000 |
---|---|---|
committer | Steve Kemp <steve@steve.org.uk> | 2012-11-23 21:49:24 +0000 |
commit | 9490880f99de4f29609757805e84400189dcf837 (patch) | |
tree | e6ded3c1dc54251255b6afa4ccd6189f6fc2f18a /lib/custodian/protocoltest/http.rb | |
parent | 3cfcef12356b98d1316ee8d3982ff581cac65be2 (diff) |
Added simple implementation - no test cases yet, no real testing carried out.
Diffstat (limited to 'lib/custodian/protocoltest/http.rb')
-rw-r--r-- | lib/custodian/protocoltest/http.rb | 156 |
1 files changed, 152 insertions, 4 deletions
diff --git a/lib/custodian/protocoltest/http.rb b/lib/custodian/protocoltest/http.rb index 133fdaf..44f76a6 100644 --- a/lib/custodian/protocoltest/http.rb +++ b/lib/custodian/protocoltest/http.rb @@ -1,3 +1,9 @@ +require 'openssl' +require 'socket' +require 'timeout' +require 'uri' + + # # The HTTP-protocol test. @@ -21,13 +27,25 @@ module Custodian # attr_reader :line - # # The URL to poll # attr_reader :url # + # The expected status + content + # + attr_reader :expected_status, :expected_content + + + # + # The actual status & content + # + attr_reader :status, :content + + + + # # Constructor # def initialize( line ) @@ -42,7 +60,6 @@ module Custodian # @url = line.split( /\s+/)[0] - if ( @url !~ /^https?:/ ) raise ArgumentError, "The target wasn't an URL" end @@ -56,6 +73,27 @@ module Custodian @inverted = false end + # + # Expected status + # + if ( line =~ /with status ([0-9]+)/ ) + @expected_status = $1.dup + else + @expected_status = "200" + end + + # + # The content we expect to find + # + if ( line =~ /with content '([^']+)'/ ) + @expected_content = $1.dup + else + @expected_content = nil + end + + @status = nil + @content = nil + end @@ -74,12 +112,122 @@ module Custodian # Run the test. # def run_test - @error = "Not implemented" - false + + # Reset state, in case we've previously run. + @error = nil + + # Parse the URL + uri = URI.parse(@url) + + # + # Ensure we have a path to request - to cover people who write: + # + # http://example.com must run http .. + # + if ( uri.path.empty? ) + uri.path = "/" + end + + # + # Connect a socket to the host. + # + socket = connect( uri.host, uri.port, uri.scheme == "https" ) + + path = uri.path + if ( uri.query ) + path = "#{url.path}?#{url.query}" + end + + req =<<EOF +GET #{path} HTTP/1.1 +Host: #{uri.host} +Connection: close + +EOF + + do_check( socket, req ) + + if ( @expected_status.to_i != @status.to_i ) + @error = "Status code was #{@status} not the expected #{@expected_status}" + return false + end + + if ( !@expected_content.nil? ) + if (! @content.match(/#{@expected_content}/i) ) + @error = "<p>The response did not contain our expected text '#{@expected_content}'</p>" + end + end + + # + # Done? + # + true end + # + # Create a socket to the appropriate host - configuring + # SSL if appropriate. + # + def connect( host, port, ssl ) + sock = TCPSocket.new(host, port) + if ( ssl) + ssl_sock = OpenSSL::SSL::SSLSocket.new( + sock, + OpenSSL::SSL::SSLContext.new("SSLv3_client") + ) + ssl_sock.sync_close = true + ssl_sock.connect + return ssl_sock + else + return sock + end + end + + + + # + # Send the request and get back the response. + # + def do_check( socket, script ) + header = true + + begin + Timeout.timeout(30, Errno::ETIMEDOUT) do + script.each do |line| + if line.is_a?(String) + socket.print line + end + end + + loop do + trans = socket.gets + + if ( header && trans =~ /HTTP\/[0-9]\.[0-9] ([0-9]+) OK/ ) + @status = $1.dup + end + if ( header && trans =~ /^$/ ) + header = false + next + end + + if ( !header ) + @content = "#{@content}#{trans}" + end + break if trans.nil? + end + socket.close + end + rescue => err + @error = err + ensure + socket.close if socket.is_a?(Socket) and not socket.closed? + end + + end + + # # If the test fails then report the error. |