Skip to content

Instantly share code, notes, and snippets.

@andrewh
Last active October 22, 2020 23:57
Show Gist options
  • Save andrewh/11379722 to your computer and use it in GitHub Desktop.
Save andrewh/11379722 to your computer and use it in GitHub Desktop.

http-ping

$ http-ping -c 5 -u google.com
Found google.com, assuming you mean http://google.com/
HTTP-PING google.com (62.253.3.89): GET request
11K bytes from www.google.co.uk: http_seq=0 status=200 time=301.44 ms
11K bytes from www.google.co.uk: http_seq=1 status=200 time=186.29 ms
12K bytes from www.google.co.uk: http_seq=2 status=200 time=185.33 ms
12K bytes from www.google.co.uk: http_seq=3 status=200 time=288.65 ms
12K bytes from www.google.co.uk: http_seq=4 status=200 time=179.4 ms

--- google.com http-ping statistics ---
5 packets transmitted, 5 ok, 0 error
min/avg/max/stddev = 179.4/228.22/301.44/61.22 ms


$ ping -c 5 google.com
PING google.com (62.253.3.93): 56 data bytes
64 bytes from 62.253.3.93: icmp_seq=0 ttl=55 time=18.917 ms
64 bytes from 62.253.3.93: icmp_seq=1 ttl=55 time=77.390 ms
64 bytes from 62.253.3.93: icmp_seq=2 ttl=55 time=19.141 ms
64 bytes from 62.253.3.93: icmp_seq=3 ttl=55 time=18.738 ms
64 bytes from 62.253.3.93: icmp_seq=4 ttl=55 time=18.946 ms

--- google.com ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 18.738/30.626/77.3900/23.382 ms/23.382 ms

How to use

$ http-ping -h
Usage: http-ping [options]
    -u, --uri URI                    URI to test (default: google.com)
    -c, --count COUNT                Number of tests (default: 5)
    -h, --help                       Show this message

TODO

  • quiet option (-q)
  • more error/interrupt handling
  • host as default option (argv[0], which ruby optparse doesn't handle too well)
#!/usr/bin/env ruby
require 'open-uri'
require 'optparse'
require 'resolv'
# so we can handle https => http, e.g. bbc.co.uk
module OpenURI
class <<self
alias_method :open_uri_original, :open_uri
alias_method :redirectable_cautious?, :redirectable?
def redirectable_safe?(uri1, uri2)
uri1.scheme.downcase == uri2.scheme.downcase ||
(uri1.scheme.downcase == "http" && uri2.scheme.downcase == "https")
end
def redirectable_all?(uri1, uri2)
redirectable_safe?(uri1, uri2) ||
(uri1.scheme.downcase == "https" && uri2.scheme.downcase == "http")
end
end
def self.open_uri(name, *rest, &block)
class << self
remove_method :redirectable?
alias_method :redirectable?, :redirectable_all?
end
self.open_uri_original name, *rest, &block
end
end
# for stddev, mean
module Enumerable
def sum
self.inject(0) { |a, i| a + i }
end
def mean
(self.sum/self.length.to_f)
end
def sample_variance
m = self.mean
sum = self.inject(0){|accum, i| accum + (i-m)**2 }
sum/(self.length - 1).to_f
end
def stddev
return Math.sqrt(self.sample_variance)
end
end
options = {}
optparse = OptionParser.new do |opts|
opts.banner = "Usage: #{File.basename($0)} [options]"
options[:uri] = "http://google.com/"
options[:count] = 5
opts.on("-u", "--uri URI", String, "URI to test (default: google.com)") do |arg|
options[:uri] = arg
end
opts.on("-c", "--count COUNT", Integer, "Number of tests (default: 5)") do |arg|
options[:count] = arg
end
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
end
optparse.parse!
if options[:uri].nil?
puts optparse
exit
end
if options[:uri][0..3] != 'http'
warn "Found #{options[:uri]}, assuming you mean http://#{options[:uri]}/"
options[:uri] = "http://#{options[:uri]}"
end
begin
results = []
uri = URI.parse(options[:uri])
puts "HTTP-PING #{uri.host}:#{uri.port} (#{Resolv.getaddress(uri.host)}): GET request"
ok = 0
error = 0
options[:count].times do |c|
t1 = Time.now.to_f
begin
response = open(uri)
t2 = Time.now.to_f
delta = (t2 - t1) * 1000
results.push(delta)
puts "#{response.size/1000}K bytes from #{response.base_uri.host}:#{response.base_uri.port}: http_seq=#{c} status=#{response.status.first} time=#{delta.round(2)} ms"
ok += 1
rescue OpenURI::HTTPError => e
response = e.message.split(" ").first
t2 = Time.now.to_f
delta = (t2 - t1) * 1000
results.push(delta)
puts "0K bytes from #{uri.host}: http_seq=#{c} status=#{response} time=#{delta.round(2)} ms"
error += 1
end
end
puts
puts "--- #{uri.host} http-ping statistics ---"
puts "#{options[:count]} packets transmitted, #{ok} ok, #{error} error"
puts "min/avg/max/stddev = #{results.min.round(2)}/#{results.mean.round(2)}/#{results.max.round(2)}/#{results.stddev.round(2)} ms"
rescue Resolv::ResolvError
warn "DNS error: #{options[:uri]}"
exit!
rescue Interrupt => e
exit!
rescue => e
puts e.message
exit!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment