From 907b1b5d35a9121bc2c2d2e94270ca8a698df1cf Mon Sep 17 00:00:00 2001 From: Steve Kemp Date: Wed, 14 Nov 2012 22:31:54 +0000 Subject: Added external curl-using HTTP fetch, to actually work. --- lib/custodian/protocol-tests/http.rb | 102 +++++---------------------- lib/custodian/webfetch.rb | 131 +++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 84 deletions(-) create mode 100755 lib/custodian/webfetch.rb (limited to 'lib/custodian') diff --git a/lib/custodian/protocol-tests/http.rb b/lib/custodian/protocol-tests/http.rb index 34fc472..3a0d1bd 100755 --- a/lib/custodian/protocol-tests/http.rb +++ b/lib/custodian/protocol-tests/http.rb @@ -1,9 +1,7 @@ #!/usr/bin/ruby1.8 -require 'net/http' -require 'net/https' -require 'uri' +require 'custodian/webfetch' class HTTPTest @@ -13,13 +11,6 @@ class HTTPTest # attr_reader :test_data - # - # The HTTP status, the HTTP response body, and the error text - # we return on failure. - # - attr_reader :status, :body, :error - - # # Save the data away. @@ -63,20 +54,26 @@ class HTTPTest # @error = nil + + # + # Run the fetch. + # + obj = WebFetch.new( @test_data["target_host"], @test_data["timeout"].to_i ) + # - # Do the fetch, if this success then we'll have the - # @status + @text setup + # If we succeeded in the fetch # - if ( getURL(@test_data["target_host"], @test_data["timeout"].to_i ) ) + if ( obj.fetch() ) # # Do we need to test for a HTTP status code? # if ( @test_data["http_status"] ) - puts "Testing for HTTP status code: #{@test_data['http_status']}" if ( @test_data['verbose'] ) - if ( @status != @test_data['http_status'].to_i) - @error = "#{@error} status code was #{@status} not #{@test_data['http_status']}" + puts "Testing for HTTP status code: #{@test_data['http_status']}" if ( @test_data['verbose'] ) + + if ( obj.status().to_i != @test_data['http_status'].to_i) + @error = "#{@error}

The HTTP status-code was '#{obj.status}' not '#{@test_data['http_status']}'.

" end end @@ -86,8 +83,8 @@ class HTTPTest if ( @test_data['http_text'] ) puts "Testing for text in the response: '#{@test_data['http_text']}'" if ( @test_data['verbose'] ) - if (! @body.match(/#{@test_data['http_text']}/i) ) - @error = "#{@error} The response did not contain our expected text '#{test_data['http_text']}'" + if (! obj.content.match(/#{@test_data['http_text']}/i) ) + @error = "#{@error}

The response did not contain our expected text '#{test_data['http_text']}

'" end end @@ -96,6 +93,7 @@ class HTTPTest return false end + @error = obj.error() return false end @@ -108,71 +106,6 @@ class HTTPTest end - # - # Retrieve a HTTP page from the web. - # - # NOTE: This came from sentinel. - def getURL (uri_str, timeout) - - timeout( timeout ) do - begin - uri_str = 'http://' + uri_str unless uri_str.match(/^http/) - url = URI.parse(uri_str) - http = Net::HTTP.new(url.host, url.port) - http.open_timeout = timeout - http.read_timeout = timeout - - if (url.scheme == "https") - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - - response = nil - - # - # Ensure we have a trailing "/" - # - if ( url.path.empty? ) - url.path = "/" - end - - if nil == url.query - response = http.start { http.get(url.path) } - else - response = http.start { http.get("#{url.path}?#{url.query}") } - end - - case response - when Net::HTTPRedirection - then - newURL = response['location'].match(/^http/)? - response['Location']:uri_str+response['Location'] - return( getURL(newURL, timeout) ) - else - @status = response.code.to_i - @body = response.body - end - - return true - rescue Errno::EHOSTUNREACH => ex - @error = "no route to host" - return false - rescue Timeout::Error => ex - @error = "time out reached" - return false - rescue Errno::ECONNREFUSED => ex - @error = "Connection refused" - return false - rescue Timeout::Error => e - @error = "TIMEOUT: #{e}" - return false - rescue => ex - @error = ex - return false - end - end - end - end @@ -192,7 +125,8 @@ if __FILE__ == $0 then "timeout" => 3, "test_port" => 80, "test_alert" => "Collector is unavailable", - "http_status" => "200" + "http_status" => "200", + "http_text" => "Bytemark Monitor" } diff --git a/lib/custodian/webfetch.rb b/lib/custodian/webfetch.rb new file mode 100755 index 0000000..5c04b31 --- /dev/null +++ b/lib/custodian/webfetch.rb @@ -0,0 +1,131 @@ +#!/usr/bin/ruby1.8 + + +require 'tempfile' + + +class WebFetch + + # + # The URL & timeout period (in seconds) we were given in the constructor + # + attr_reader :url, :timeout + + # + # The HTTP status code, and content, we received from fetching the URL + # + attr_reader :status, :text, :error + + + + # + # Constructor + # + def initialize( url, timeout = 10 ) + @url = url + @timeout = timeout + + # defaults + @status = -1 + @error = "" + @text = "" + end + + + + # + # Perform the fetch. + # + # Return true on success. + # + def fetch + + # + # Generate a temporary file to contain the header from the server. + # + tmp_head = Tempfile.new('curl-header') + head = tmp_head.path + + # + # Generate a temporary file to contain the body from the server. + # + tmp_body = Tempfile.new('curl-body') + body = tmp_body.path + + # + # Shell out to curl (!!!) to do the fetch. + # + system( "curl --max-time #{timeout} --silent --location --insecure --dump-header #{head} --out #{body} --silent #{@url}") + + + # + # If both files are size zero then we clearly failed. + # + if ( ( File.size( body ) == 0 ) || + ( File.size( head ) == 0 ) ) + + # + # Cleanup + # + File.unlink( body ) if ( File.exists?( body ) ) + File.unlink( head ) if ( File.exists?( head ) ) + + # + # Save the error. + # + @error = "Fetch failed" + return false + end + + + # + # Get the HTTP status code, by parsing the HTTP headers. + # + File.open( head, "r").each_line do |line| + if ( line =~ /HTTP\/[0-9]\.[0-9]\s+([0-9]+)\s+/ ) + @status = $1.dup + end + end + + # + # Get the body from the server, by parsing the temporary file. + # + File.open( body, "r").each_line do |line| + @text << line + end + + # + # Cleanup. We're done. + # + File.unlink( body ) if ( File.exists?( body ) ) + File.unlink( head ) if ( File.exists?( head ) ) + + return true + end + + + # + # Return the HTTP status code the server responded with, if the + # fetch was successful. + # + def status + @status + end + + # + # Return the HTTP content the server responded with, if the + # fetch was successful. + # + def content + @text + end + + # + # Return the error, if the fetch failed. + # + def error + @error + end + +end + -- cgit v1.2.1