Whois::Record::Parser object, as the name suggest, actually belongs to the
Whois::Record namespace. However, this element is such important to deserve its own documentation section.
The parser architecture allows you to access the WHOIS responses as an object. The parsers decompose the response
String and offers a standardized API to access its content. For instance, to get the date the record has been created, just call the
created_on method, no matter you are querying the
# Example: Accessing a WHOIS record, the object oriented way r = Whois.whois("google.it") r.created_on # => Fri Dec 10 00:00:00 +0100 1999 r.expires_on # => Sat Nov 27 00:00:00 +0100 2010
The Problem with WHOIS Record Parsing
As explained in the
Whois::Record section, an record is composed by one or more
parts. Each part represents the response from a specific WHOIS server. Because the WHOIS doesn't force WHOIS servers to follow an unique response layout, each server needs its own dedicated parser.
Have a look at the following records to better understand the differences.
********************************************************************* * Please note that the following result could be a subgroup of * * the data contained in the database. * * * * Additional information can be visualized at: * * http://www.nic.it/cgi-bin/Whois/whois.cgi * ********************************************************************* Domain: google.it Status: ACTIVE Created: 1999-12-10 00:00:00 Last Update: 2009-12-13 00:03:01 Expire Date: 2010-11-27 Registrant Name: Google Ireland Holdings Organization: Google Ireland Holdings ContactID: GOOG175-ITNIC Address: 30 Herbert Street Dublin 2 IE IE Created: 2008-11-27 16:47:22 Last Update: 2008-11-27 16:47:22
Whois Server Version 2.0 Domain names in the .com and .net domains can now be registered with many different competing registrars. Go to http://www.internic.net for detailed information. Domain Name: AISCUNEO.COM Registrar: GODADDY.COM, INC. Whois Server: whois.godaddy.com Referral URL: http://registrar.godaddy.com Name Server: NS1.DREAMHOST.COM Name Server: NS2.DREAMHOST.COM Name Server: NS3.DREAMHOST.COM Status: clientDeleteProhibited Status: clientRenewProhibited Status: clientTransferProhibited Status: clientUpdateProhibited Updated Date: 21-jan-2010 Creation Date: 24-jan-2009 Expiration Date: 24-jan-2011 >>> Last update of whois database: Fri, 05 Mar 2010 21:53:17 UTC <<<
Moreover, if you consider the
Thin data model, a single
.com query often requires at least two parsers. One for the Verisign request and one for the final registrar.
I know what you are thinking and the record is yes: in order to support all existing WHOIS servers and registrars, the
Whois library should provide more than 500 different parsers. And this is exactly one of the major development goal. Unfortunately, as you might imagine, this requires a huge development effort.
God save the Standards!
Whois::Record::Parser object acts as a
proxy between the
Whois::Record object and the
As explained in the section above, a
Whois::Record is composed by one or more
parts and each
Whois::Record::Part has its own custom parser.
Whois::Record::Part-level parsers must implements the
Whois::Record::Parser::Base abstract class.
Parsers define a standard API and two parsers can actually overlaps. For instance, if a
.com response contains two parts and each parser supports the
nameservers property, then you need an element to forward the request to the most appropriate endpoint. That's the
Whois::Record::Parser knows about all
Whois::Record::Part-level parsers and automatically returns the most appropriate value for a specific property.
# Example: Using the Whois::Record::Parser to access the Whois::Record data r = Whois.whois("google.it") p = r.parser p.created_on # => Fri Dec 10 00:00:00 +0100 1999 p.expires_on # => Sat Nov 27 00:00:00 +0100 2010
Whois::Record::Parser defines a specific list of record properties. The list is designed in order to include the most common information available in a WHOIS response.
Whois::Record::Parser::PROPERTIES returns the current list.
# Example: Getting the list of defined record properties Whois::Record::Parser::PROPERTIES => [:disclaimer, :domain, :domain_id, :referral_whois, :referral_url, :status, :registered?, :available?, :created_on, :updated_on, :expires_on, :registrar, :registrant, :admin, :technical, :nameservers]
Here's the full list of available properties.
You can access each of this property using the corresponding instance method.
# Example: Accessing record properties using the instance methods r = Whois.whois("google.it") p = r.parser p.disclaimer # => "..." p.domain_id # => nil
The method can either return the value or raise a
Whois::ParserError exception, depending whether the value is supported or not.
When you access a property, you can expect two different behaviors:
- the method value
- an exception
The first case is the most simple. If at least one
Whois::Record::Part-level parser supports the specified property, then the the last parser which implements it wins and the value is returned.
Have a look at the following examples.
# Example: The Record contains two parts corresponding to the responses from the following WHOIS servers: whois.foo.com supports #domain, #domain_id whois.bar.com supports #domain, #disclaimer p = Whois.whois("google.it").parser # both parsers support the property, last value returned p.domain # => value from whois.bar.com # the first parser supports the property, value returned p.domain_id # => value from whois.foo.com # the second parser supports the property, value returned p.disclaimer # => value from whois.bar.com # the property is not supported, exception raised p.created_on
The last statement raises an Exception because the property is not supported nor not available. There's a slight difference between a not supported and not available property. View the (yet to come)
Whois::Record::Parser::Base base for a detailed explanation.
For now, you just need to know that a property might raise 2 different exceptions according to its flag:
All these exceptions inherits from
Record#property vs Parser#property
As you probably already noticed from the examples you read so far, you can either access an record property from the
Whois::Record object or from the underlying
# Example: Accessing an record properties from # Whois::Record and Whois::Record::Parser objects r = Whois.whois("google.it") r.created_on # => Fri Dec 10 00:00:00 +0100 1999 r.parser.created_on # => Fri Dec 10 00:00:00 +0100 1999
The values are absolutely equivalent.
# Example: Demonstrating the equality between # Whois::Record and Whois::Record::Parser properties r = Whois.whois("google.it") r.created_on == a.parser.created_on # => true
However, there's a technical difference between the two methods.
In the section above you learnt a property can either return a value or raise an exception. You can check whether a property is supported or not using the
# Example: Checking if the property is supported r = Whois.whois("google.it") r.property_supported?(:domain) # => false r.parser.property_supported?(:domain) # => false
The main difference between accessing a property at
Whois::Record level or
Whois::Record::Parser level is that the former never raises exceptions. Instead, if a property is not supported the
Whois::Record silently returns
# Example: Checking if the property is supported r = Whois.whois("google.it") r.domain # => nil r.parser.domain # => AttributeNotSupported
Usually, it's more convenient to access a property at record level unless you need a more granular control.