Skip to content

Commit f13b722

Browse files
authorMarco Giosa
committed
version 1.0.0
1 parent 08397b4 commit f13b722

File tree

3 files changed

+153
-0
lines changed

3 files changed

+153
-0
lines changed

checkhost.gemspec

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Gem::Specification.new do |s|
2+
s.name = 'checkhost'
3+
s.version = '1.0.0'
4+
s.date = '2015-12-26'
5+
s.summary = "Ruby check-host.net API"
6+
s.description = "Gem to check-host.net public API"
7+
s.authors = ["Marco Giosa"]
8+
s.email = 'marco.giosa@me.com'
9+
s.files = ["lib/checkhost.rb"]
10+
s.homepage = 'https://github.com/markkuit/checkhost-ruby'
11+
s.license = 'MIT'
12+
end

lib/checkhost.rb

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env ruby
2+
require 'net/http'
3+
require 'json'
4+
5+
class CheckHost
6+
attr_reader :nodes
7+
8+
def initialize(host, options = {:type => 'http', :max_nodes => 3})
9+
supported_types = %w(ping http tcp dns udp)
10+
raise(ArgumentError, "unsupported check type (valid values: #{supported_types.join(' ')})") unless supported_types.include?(options[:type])
11+
raise(ArgumentError, "maximum number of nodes has to be integer") unless options[:max_nodes].is_a? Integer
12+
13+
@host = host
14+
@options = options
15+
@nodes = []
16+
end
17+
18+
def run
19+
res = parse(query(:newcheck, {:host => @host, :type => @options[:type], :max_nodes => @options[:max_nodes]}))
20+
@id = res['request_id']
21+
@nodes_info = res['nodes']
22+
@nodes_info.each do |key, value|
23+
@nodes.push(key);
24+
end
25+
end
26+
27+
def node_info(code) # cc, country, location
28+
if @nodes_info.has_key?(code) then
29+
return {:cc => @nodes_info[code][0],
30+
:country => @nodes_info[code][1],
31+
:location => @nodes_info[code][2]}
32+
end
33+
end
34+
35+
def check
36+
res_data = {}
37+
res = parse(query(:results, {:request_id => @id}))
38+
res.each do |node, value|
39+
if !value.nil? then value.flatten!(1) end
40+
if !value.nil? && !value[0].nil? then # 'cause some return [nil] and can't flatten more
41+
node_data = {}
42+
case @options[:type]
43+
when 'ping' # avg_ok, avg_timeout, avg_malformed, ok_count, timeout_count, malformed_count, ip
44+
node_data[:ok_count] = 0
45+
node_data[:timeout_count] = 0
46+
node_data[:malformed_count] = 0
47+
node_data[:avg_ok] = 0
48+
node_data[:avg_timeout] = 0
49+
node_data[:avg_malformed] = 0
50+
51+
value.each do |info|
52+
node_data[:ip] = info[2] if(info[2])
53+
case info[0]
54+
when 'OK'
55+
node_data[:avg_ok] += info[1]
56+
node_data[:ok_count] += 1
57+
when 'TIMEOUT'
58+
node_data[:avg_timeout] += info[1]
59+
node_data[:timeout_count] += 1
60+
when 'MALFORMED'
61+
node_data[:avg_malformed] += info[1]
62+
node_data[:malformed_count] += 1
63+
end
64+
end
65+
66+
if(node_data[:ok_count] > 0) then
67+
node_data[:avg_ok] = (node_data[:avg_ok]*1000).to_i
68+
node_data[:avg_ok] /= node_data[:ok_count]
69+
end
70+
if(node_data[:timeout_count] > 0) then
71+
node_data[:avg_timeout] = (node_data[:avg_timeout]*1000).to_i
72+
node_data[:avg_timeout] /= node_data[:timeout_count]
73+
end
74+
if(node_data[:malformed_count] > 0) then
75+
node_data[:avg_malformed] = (node_data[:avg_malformed]*1000).to_i
76+
node_data[:avg_malformed] /= node_data[:malformed_count]
77+
end
78+
when 'http' # success, time, message, code, ip
79+
node_data[:success] = value[0]
80+
node_data[:time] = (value[1]*1000).to_i
81+
node_data[:message] = value[2]
82+
node_data[:code] = value[3].to_i
83+
node_data[:ip] = value[4]
84+
when 'tcp', 'udp' # error, time, ip
85+
node_data[:error] = value[0]['error']
86+
node_data[:time] = (value[0]['time']*1000).to_i
87+
node_data[:ip] = value[0]['address']
88+
when 'dns' # a, aaaa, ttl
89+
node_data[:a] = value[0]['A']
90+
node_data[:aaaa] = value[0]['AAAA']
91+
node_data[:ttl] = value[0]['TTL']
92+
end
93+
res_data[node] = node_data
94+
else res_data[node] = nil end
95+
end
96+
return res_data
97+
end
98+
99+
private
100+
def query(action, data) # action: newcheck, results; data(hash): newcheck:: type, host, max_nodes | results:: request_id
101+
headers = {'Accept' => 'application/json'}
102+
103+
case action
104+
when :newcheck
105+
uri = URI("http://check-host.net/check-#{data[:type]}?host=#{data[:host]}&max_nodes=#{data[:max_nodes]}")
106+
api = Net::HTTP.new(uri.host)
107+
api.get(uri, headers).body
108+
when :results
109+
uri = URI("http://check-host.net/check-result/#{data[:request_id]}")
110+
api = Net::HTTP.new(uri.host)
111+
api.get(uri, headers).body
112+
end
113+
end
114+
115+
def parse(json)
116+
res = JSON.parse(json)
117+
raise "check-host.net returned error: #{res['error']}" if res.has_key?('error')
118+
return res
119+
end
120+
end

lib/test.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env ruby
2+
require 'checkhost'
3+
res = {}
4+
5+
google = CheckHost.new('google.com', {:type => 'http', :max_nodes => 3})
6+
google.run
7+
res = google.check until !res.empty? && !res.has_value?(nil)
8+
9+
print 'Check nodes: '
10+
google.nodes.each do |node|
11+
node = google.node_info(node)
12+
print "#{node[:country]}(#{node[:location]}) "
13+
end
14+
puts "\n\n"
15+
res.each do |node, result|
16+
country = google.node_info(node)[:country]
17+
message = result[:message]
18+
time = result[:time]
19+
20+
puts "#{country}: #{message} (in #{time}ms)"
21+
end

0 commit comments

Comments
 (0)