Ruby Whois preview: WHOIS answer and parser

About two month ago I blogged about a brand new release of the Whois GEM for Ruby. Today I'd like to show you a couple of really powerful features introduced with the new Whois version, currently available in EAP.

This release contains two major changes: the introduction of the Answer object and the WHOIS parsers. The final version of Whois 0.8.0 will be available by the end of September.

Answer object

When you run a query with Whois 0.5.0, the library returns the server answer as a simple string.

s = Whois.Client.new.query "simonecarletti.it"
# => "..."
s.class
# => String

There's nothing wrong with this. However, a String is a really simple object and it doesn't offer any WHOIS-specific features. For instance, if you want to know whether the domain is available, you need some extra work to parse the string and get the result.

s = Whois.Client.new.query "simonecarletti.it"
if s =~ /Registrant/
  # registered
else
  # available
end

Also, the string doesn't have any historical knowledge. It doesn't know where it originates from, which server returned that specific answer or how many requests composes the final response.

Starting from Whois 0.8.0, every WHOIS query returns a new Whois::Answer instance.

s = Whois.Client.new.query "simonecarletti.it"
# => "..."
s.class
# => Whois::Answer

This object acts mostly as a String. It supports the most common String methods including #inspect, #to_s, #match and also equality comparison.

>> a = Whois.query "simonecarletti.it"
=> "nn*********************************************************************n* Please note that the following result could be a subgroup of      *n* the data contained in the database.                               *n*                                                                   *n* Additional information can be visualized at:                      *n* http://www.nic.it/cgi-bin/Whois/whois.cgi                         *n*********************************************************************nnDomain:             simonecarletti.itnStatus:             ACTIVEnCreated:            2007-08-27 09:32:27nLast Up>> a == a.to_s
=> true
>> a.match?(/Registrant/)
=> true

The Answer object itself is much more than a simple enhanced string. It allows you to get some really interesting details about which server originated the response.

>> s = a.server
=> #<Whois::Server::Adapters::Standard>

# The server host
>> s.host
=> "whois.nic.it"

# The server allocation, in this case the value for the TLD
>> s.allocation
=> ".it"

Last but not least, the Answer class let you parse the answer with a full object-oriented syntax. Hey, wait… did I say parse?

Whois Parser

Whois parsers are the feature I'm most proud of about this library. No other WHOIS library provides a similar advanced feature to access registry data.

An example is better than thousand words.

>> a = Whois.query "simonecarletti.it"

# Is the domain available?
>> a.available?
=> false
>> a.registered?
=> true

# Give me some details about creation and expiration date
>> a.created_on
=> Mon Aug 27 09:32:27 +0200 2007
>> a.expires_on.strftime("%Y")
=> "2010"

# Hey, the site doesn't work. Who is the server administrator?
>> c = a.technical
=> #<Whois::Answer::Contact>
>> c.name
=> "Simone Carletti"
>> c.email
=> nil

Isn't that cool? And this is just a small demonstration of what you can do with data parsers.

For instance, you can also compare two response to check whether registry data changed in from the last time you sent a request.

# get the first response from the database
a = Whois.find_by_host("google.it").last

# get the new response
b = Whois.query("google.it")

# compare the old response with the new one
a.changed?(b)
# => false

If you want to learn more about what you can do with Whois parsers I encourage you to browse the library repository.