Skip to content

Instantly share code, notes, and snippets.

@lachlan
Last active February 21, 2016 22:21
Show Gist options
  • Save lachlan/d5a16986e4553be79778 to your computer and use it in GitHub Desktop.
Save lachlan/d5a16986e4553be79778 to your computer and use it in GitHub Desktop.
Threaded HTTP POST of content to an HTTP Server returning response duration statistics
# https post a payload to a web server with basic authentication
require 'net/https'
require 'benchmark'
request_count = 1
thread_count = 10
protocol = 'http' # or 'https'
host = 'www.example.com'
port = 80
path = '/path/file'
# http basic authentication
user = 'username'
pass = 'password'
content = "Example content to be HTTP posted"
content_type = 'text/plain'
content_encoding = 'gzip' # or nil if compression not required
def compress(input, level=Zlib::DEFAULT_COMPRESSION, strategy=Zlib::DEFAULT_STRATEGY)
output = StringIO.new("w")
gz = Zlib::GzipWriter.new(output, level, strategy)
gz.write(input)
gz.close
output.string
end
def mean(ary)
ary.inject(0) { |sum, i| sum += i }/ary.length.to_f
end
def stddev(ary, mean)
Math.sqrt( (ary.inject(0) { |dev, i| dev += (i - mean) ** 2}/ary.length.to_f) )
end
uri = URI.parse(protocol + '://' + host + ':' + port.to_s + path)
headers = {}
threads = []
io = $stdout
if defined? content_type and !content_type.nil?
headers['Content-Type'] = content_type
else
headers['Content-Type'] = 'application/octet-stream'
end
if defined? content_encoding and !content_encoding.nil?
headers['Content-Encoding'] = content_encoding
end
if headers['Content-Encoding'] == 'gzip'
content = compress content
end
if defined? user and !user.nil?
pass = '' unless defined? pass and !pass.nil?
headers['Authorization'] = 'Basic ' + [user + ':' + pass].pack('m')
end
thread_count.times do
threads << Thread.new do
durations = []
total, successes, failures = 0, 0, 0
server = Net::HTTP.new(uri.host, uri.port, nil) # the nil here disables use of the configured HTTP_PROXY
server.keep_alive_timeout = 60
server.use_ssl = uri.scheme == 'https'
server.verify_mode = OpenSSL::SSL::VERIFY_NONE
# uncomment following line to see http requests and responses printed to the console
# server.set_debug_output $stderr
request_count.times do
payload = content
durations << Benchmark.realtime do
begin
response = server.post(uri.request_uri, payload, headers)
successes += 1
rescue => ex
puts ex
failures += 1
end
end
total += 1
end
Thread.current[:durations] = durations
Thread.current[:successes] = successes
Thread.current[:failures] = failures
Thread.current[:total] = total
end
end
samples = []
total, successes, failures = 0, 0, 0
threads.each do |thread|
thread.join
samples << thread[:durations]
total += thread[:total]
successes += thread[:successes]
failures += thread[:failures]
end
samples.flatten!
average = mean(samples)
deviation = stddev(samples, average)
printf "%s HTTP response analysis: μ = %f s, σ = %f s, n = %d, successes = %d, failures = %d", uri, average, deviation, total, successes, failures
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment