Permalink
Browse files

Ability to pass a custom query_handler to the Server adapter (closes G…

  • Loading branch information...
2 parents b629cf7 + 01130e5 commit 8aa56d1b8668770b2d4225e3b3427b0a6fdbce10 @weppos committed Oct 29, 2012
View
@@ -7,6 +7,8 @@
- NEW: ruby-whois learns the -h option to pass whois hostname on the fly
+- NEW: Ability to pass a custom query_handler to the Server adapter (GH-189)
+
- CHANGED: Dropped support for Ruby 1.8
- CHANGED: Renamed Whois::Record::Scanners::Ast to Renamed Whois::Record::Scanners::Nodable
@@ -46,6 +48,11 @@
- FIXED: whois.nic.cz should support multiple status (GH-190).
+### Backward Incompatibilities
+
+- Whois::Server#query has been renamed to Whois::Server#lookup
+
+
## Release 2.7.0
* SERVER: Added .IQ TLD server (GH-171).
View
@@ -84,7 +84,7 @@ def available?(object)
# This is a technical limitation. Browse the lib/whois/record/parsers folder
# to view all available parsers.
#
- # @param [String] string The string to be sent as query parameter.
+ # @param [String] object The string to be sent as query parameter.
# It is intended to be a domain name, otherwise this method
# may return unexpected responses.
# @return [Boolean]
View
@@ -89,7 +89,7 @@ def query(object)
Timeout::timeout(timeout) do
@server = Server.guess(string)
@server.configure(settings)
- @server.query(string)
+ @server.lookup(string)
end
end
@@ -9,7 +9,7 @@
require 'whois/record/part'
require 'whois/record'
-require 'socket'
+require 'whois/server/socket_handler'
module Whois
@@ -20,20 +20,13 @@ class Base
# Default WHOIS request port.
DEFAULT_WHOIS_PORT = 43
-
# Default bind hostname.
DEFAULT_BIND_HOST = "0.0.0.0"
- # Array of connection errors to rescue and wrap into a {Whois::ConnectionError}
- RESCUABLE_CONNECTION_ERRORS = [
- Errno::ECONNRESET,
- Errno::EHOSTUNREACH,
- Errno::ECONNREFUSED,
- SocketError,
- ]
-
+ class_attribute :query_handler
+ self.query_handler = SocketHandler.new
- # @return [Symbol] The type of WHOIS server
+ # @return [Symbol] The type of WHOIS server.
attr_reader :type
# @return [String] The allocation this server is responsible for.
attr_reader :allocation
@@ -68,7 +61,6 @@ def initialize(type, allocation, host, options = {})
# Checks self and other for equality.
#
# @param [The Whois::Server::Adapters::Base] other
- #
# @return [Boolean] Returns true if the other is the same object,
# or <tt>other</tt> attributes matches this object attributes.
#
@@ -98,20 +90,19 @@ def configure(settings)
end
- # Performs a Whois query for <tt>string</tt>
+ # Performs a Whois lookup for <tt>string</tt>
# using the current server adapter.
#
- # @param [String] string The string to be sent as query parameter.
- #
- # @return [Whois::Record]
- #
# Internally, this method calls {#request}
# using the Template Method design pattern.
#
- # server.query("google.com")
+ # server.lookup("google.com")
# # => Whois::Record
#
- def query(string)
+ # @param [String] string The string to be sent as query parameter.
+ # @return [Whois::Record]
+ #
+ def lookup(string)
buffer_start do |buffer|
request(string)
Whois::Record.new(self, buffer)
@@ -125,26 +116,23 @@ def query(string)
# This is the heart of the Template Method design pattern.
#
# @param [String] string The string to be sent as query parameter.
- #
- # @raise [NotImplementedError]
# @return [void]
+ # @raise [NotImplementedError]
# @abstract
#
def request(string)
raise NotImplementedError
end
- private
+ private
# Store a record part in {#buffer}.
#
# @param [String] body
# @param [String] host
# @return [void]
#
- # @api public
- #
def buffer_append(body, host)
@buffer << Whois::Record::Part.new(:body => body, :host => host)
end
@@ -157,8 +145,14 @@ def buffer_start
result
end
- # @api public
- def query_the_socket(query, host, port = nil)
+ # Prepares and passes the query to the {#query_handler}.
+ #
+ # @param [String] query
+ # @param [String] host
+ # @param [String] port
+ # @return [String]
+ #
+ def query_prepare(query, host, port = nil)
args = []
args.push(host)
args.push(port || options[:port] || DEFAULT_WHOIS_PORT)
@@ -178,25 +172,10 @@ def query_the_socket(query, host, port = nil)
args.push(options[:bind_port]) if options[:bind_port]
end
- ask_the_socket(query, *args)
-
- rescue *RESCUABLE_CONNECTION_ERRORS => error
- raise ConnectionError, "#{error.class}: #{error.message}"
+ self.class.query_handler.call(query, *args)
end
- # This method handles the lowest connection
- # to the WHOIS server.
- #
- # This is for internal use only!
- #
- # @api private
- def ask_the_socket(query, *args)
- client = TCPSocket.new(*args)
- client.write("#{query}\r\n") # I could use put(foo) and forget the \n
- client.read # but write/read is more symmetric than puts/read
- ensure # and I really want to use read instead of gets.
- client.close if client # If != client something went wrong.
- end
+ alias :query_the_socket :query_prepare
end
@@ -0,0 +1,66 @@
+#--
+# Ruby Whois
+#
+# An intelligent pure Ruby WHOIS client and parser.
+#
+# Copyright (c) 2009-2012 Simone Carletti <weppos@weppos.net>
+#++
+
+
+require 'socket'
+require 'whois/errors'
+
+
+module Whois
+ class Server
+
+ # The SocketHandler is the default query handler provided with the
+ # Whois library. It performs the WHOIS query using a synchronous
+ # socket connection.
+ class SocketHandler
+
+ # Array of connection errors to rescue
+ # and wrap into a {Whois::ConnectionError}
+ RESCUABLE_CONNECTION_ERRORS = [
+ Errno::ECONNRESET,
+ Errno::EHOSTUNREACH,
+ Errno::ECONNREFUSED,
+ SocketError,
+ ]
+
+ # Performs the Socket request.
+ #
+ # @todo *args might probably be a Hash.
+ #
+ # @param [String] query
+ # @param [Array] args
+ # @return [String]
+ #
+ def call(query, *args)
+ execute(query, *args)
+ rescue *RESCUABLE_CONNECTION_ERRORS => error
+ raise ConnectionError, "#{error.class}: #{error.message}"
+ end
+
+ # Executes the low-level Socket connection.
+ #
+ # It opens the socket passing given +args+,
+ # sends the +query+ and reads the response.
+ #
+ # @param [String] query
+ # @param [Array] args
+ # @return [String]
+ #
+ # @api private
+ #
+ def execute(query, *args)
+ client = TCPSocket.new(*args)
+ client.write("#{query}\r\n") # I could use put(foo) and forget the \n
+ client.read # but write/read is more symmetric than puts/read
+ ensure # and I really want to use read instead of gets.
+ client.close if client # If != client something went wrong.
+ end
+ end
+
+ end
+end
View
@@ -8,10 +8,10 @@
it "works" do
with_definitions do
Whois::Server.define(:tld, ".it", "whois.nic.it")
- Whois::Server::Adapters::Standard.any_instance \
- .expects(:ask_the_socket) \
- .with("example.it", "whois.nic.it", 43) \
- .returns(response)
+ Whois::Server::Adapters::Base.
+ query_handler.expects(:call).
+ with("example.it", "whois.nic.it", 43).
+ returns(response)
record = Whois.query("example.it")
@@ -29,10 +29,10 @@
it "binds the WHOIS query to given host and port" do
with_definitions do
Whois::Server.define(:tld, ".it", "whois.nic.it")
- Whois::Server::Adapters::Standard.any_instance \
- .expects(:ask_the_socket) \
- .with("example.it", "whois.nic.it", 43, "192.168.1.1", 3000) \
- .returns(response)
+ Whois::Server::Adapters::Base.
+ query_handler.expects(:call).
+ with("example.it", "whois.nic.it", 43, "192.168.1.1", 3000).
+ returns(response)
client = Whois::Client.new(:bind_host => "192.168.1.1", :bind_port => 3000)
client.query("example.it")
@@ -44,10 +44,10 @@
it "binds the WHOIS query to given port and defaults host" do
with_definitions do
Whois::Server.define(:tld, ".it", "whois.nic.it")
- Whois::Server::Adapters::Standard.any_instance \
- .expects(:ask_the_socket) \
- .with("example.it", "whois.nic.it", 43, Whois::Server::Adapters::Base::DEFAULT_BIND_HOST, 3000) \
- .returns(response)
+ Whois::Server::Adapters::Base.
+ query_handler.expects(:call).
+ with("example.it", "whois.nic.it", 43, Whois::Server::Adapters::Base::DEFAULT_BIND_HOST, 3000).
+ returns(response)
client = Whois::Client.new(:bind_port => 3000)
client.query("example.it")
@@ -59,8 +59,8 @@
it "forces the WHOIS query to given host" do
with_definitions do
Whois::Server.define(:tld, ".it", "whois.nic.it")
- Whois::Server::Adapters::Standard.any_instance.
- expects(:ask_the_socket).
+ Whois::Server::Adapters::Base.
+ query_handler.expects(:call).
with("example.it", "whois.example.com", 43).
returns(response)
@@ -11,7 +11,7 @@ def fixture(*names)
File.join(SPEC_ROOT, "fixtures", *names)
end
-private
+ private
# Temporary resets Server @@definitions
# to let the test setup a custom definition list.
Oops, something went wrong.

0 comments on commit 8aa56d1

Please sign in to comment.