Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Using HTTP HEAD instead of GET #10

Closed
wants to merge 1 commit into from

2 participants

@bkutil

The changes were a bit more extensive than I previously thought. They were needed to correctly use HEAD in case of redirects.

@djberg96
Owner

Hm, something's happened, I can't auto merge now.

@bkutil

I can re-clone from your current master and create a fresh branch without the is_a? patch. Or feel free to cherry pick + amend my changes.

@djberg96
Owner

Please re-clone if you don't mind. :)

@bkutil

Yep, no prob.

Balazs Kutil Use HTTP head instead of GET by default
This patch replaces the http GET request with HEAD. HEAD requests should
be handled identically, but the response does not contain message
body. GET will still be used when @get_request option is set to true.

Replacing the get_response (which calls GET internally) with a new
http HEAD request would mean code duplication. Thus, the part that does
the actual ping is refactored to a separate private method.
This also means that new requests resulting from redirections are
now subject to timeout limit and they'll correctly use https.

Signed-off-by: Balazs Kutil <kutil.balazs@gmail.com>
ff721cd
@bkutil bkutil closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 4, 2011
  1. Use HTTP head instead of GET by default

    Balazs Kutil authored
    This patch replaces the http GET request with HEAD. HEAD requests should
    be handled identically, but the response does not contain message
    body. GET will still be used when @get_request option is set to true.
    
    Replacing the get_response (which calls GET internally) with a new
    http HEAD request would mean code duplication. Thus, the part that does
    the actual ping is refactored to a separate private method.
    This also means that new requests resulting from redirections are
    now subject to timeout limit and they'll correctly use https.
    
    Signed-off-by: Balazs Kutil <kutil.balazs@gmail.com>
This page is out of date. Refresh to see the latest.
Showing with 72 additions and 43 deletions.
  1. +63 −41 lib/net/ping/http.rb
  2. +9 −2 test/test_net_ping_http.rb
View
104 lib/net/ping/http.rb
@@ -30,6 +30,9 @@ class Ping::HTTP < Ping
# OpenSSL certificate verification mode. The default is VERIFY_NONE.
attr_accessor :ssl_verify_mode
+ # Use GET request instead HEAD. The default is false.
+ attr_accessor :get_request
+
# Creates and returns a new Ping::HTTP object. The default port is the
# port associated with the URI. The default timeout is 5 seconds.
#
@@ -37,6 +40,7 @@ def initialize(uri=nil, port=nil, timeout=5)
@follow_redirect = true
@redirect_limit = 5
@ssl_verify_mode = OpenSSL::SSL::VERIFY_NONE
+ @get_request = false
port ||= URI.parse(uri).port if uri
@@ -64,51 +68,35 @@ def ping(host = @host)
start_time = Time.now
- begin
- response = nil
- uri_path = uri.path.empty? ? '/' : uri.path
- headers = { }
- headers["User-Agent"] = user_agent unless user_agent.nil?
- Timeout.timeout(@timeout) do
- http = Net::HTTP.new(uri.host, uri.port)
- if uri.scheme == 'https'
- http.use_ssl = true
- http.verify_mode = @ssl_verify_mode
- end
- request = Net::HTTP::Get.new(uri_path)
- response = http.start{ |h| h.request(request) }
- end
- rescue Exception => err
- @exception = err.message
- else
- if response.is_a?(Net::HTTPSuccess)
- bool = true
- else
- if @follow_redirect
- @warning = response.message
- rlimit = 0
-
- # Any response code in the 300 range is a redirect
- while response.code.to_i >= 300 && response.code.to_i < 400
- if rlimit >= redirect_limit
- @exception = "Redirect limit exceeded"
- break
- end
- redirect = URI.parse(response['location'])
- redirect = uri + redirect if redirect.relative?
- response = Net::HTTP.get_response(redirect.host, redirect.path, @port)
- rlimit += 1
- end
+ response = do_ping(uri)
+
+ if response.is_a?(Net::HTTPSuccess)
+ bool = true
+ elsif redirect?(response) # Check code, HTTPRedirection does not always work
+ if @follow_redirect
+ @warning = response.message
+ rlimit = 0
- if response.is_a?(Net::HTTPSuccess)
- bool = true
- else
- @warning = nil
- @exception ||= response.message
+ while redirect?(response)
+ if rlimit >= redirect_limit
+ @exception = "Redirect limit exceeded"
+ break
end
+ redirect = URI.parse(response['location'])
+ redirect = uri + redirect if redirect.relative?
+ response = do_ping(redirect)
+ rlimit += 1
+ end
+
+ if response.is_a?(Net::HTTPSuccess)
+ bool = true
else
- @exception = response.message
+ @warning = nil
+ @exception ||= response.message
end
+
+ else
+ @exception = response.message
end
end
@@ -123,5 +111,39 @@ def ping(host = @host)
alias follow_redirect? follow_redirect
alias uri host
alias uri= host=
+
+ private
+
+ def redirect?(response)
+ response && response.code.to_i >= 300 && response.code.to_i < 400
+ end
+
+ def do_ping(uri)
+ response = nil
+ begin
+ uri_path = uri.path.empty? ? '/' : uri.path
+ headers = { }
+ headers["User-Agent"] = user_agent unless user_agent.nil?
+ Timeout.timeout(@timeout) do
+ http = Net::HTTP.new(uri.host, uri.port)
+
+ if uri.scheme == 'https'
+ http.use_ssl = true
+ http.verify_mode = @ssl_verify_mode
+ end
+
+ if @get_request == true
+ request = Net::HTTP::Get.new(uri_path)
+ else
+ request = Net::HTTP::Head.new(uri_path)
+ end
+
+ response = http.start{ |h| h.request(request) }
+ end
+ rescue Exception => err
+ @exception = err.message
+ end
+ response
+ end
end
end
View
11 test/test_net_ping_http.rb
@@ -16,8 +16,9 @@ def setup
@uri_https = 'https://encrypted.google.com'
FakeWeb.register_uri(:get, @uri, :body => "PONG")
- FakeWeb.register_uri(:get, @uri_https, :body => "PONG")
- FakeWeb.register_uri(:get, "http://jigsaw.w3.org/HTTP/300/302.html",
+ FakeWeb.register_uri(:head, @uri, :body => "PONG")
+ FakeWeb.register_uri(:head, @uri_https, :body => "PONG")
+ FakeWeb.register_uri(:head, "http://jigsaw.w3.org/HTTP/300/302.html",
:body => "PONG",
:location => "#{@uri}",
:status => ["302", "Found"])
@@ -168,6 +169,12 @@ def setup
assert_true(@http.ping)
end
+ test 'ping with get option' do
+ @http = Net::Ping::HTTP.new(@uri)
+ @http.get_request = true
+ assert_true(@http.ping)
+ end
+
def teardown
@uri = nil
@http = nil
Something went wrong with that request. Please try again.