Hookd Ruby Client
Ruby client library for Hookd, a DNS/HTTP interaction server for security testing and debugging.
Installation
Add this line to your application's Gemfile:
gem 'hookd-client'
Or install it yourself as:
gem install hookd-client
Usage
Basic Example
require 'hookd'
require 'typhoeus'
# Initialize the client
client = Hookd::Client.new(
server: "https://hookd.example.com",
token: ENV['HOOKD_TOKEN']
)
# Register a new hook
hook = client.register
puts "DNS endpoint: #{hook.dns}"
puts "HTTP endpoint: #{hook.http}"
puts "HTTPS endpoint: #{hook.https}"
# Make a request to the HTTP endpoint to simulate an interaction
Typhoeus.get(hook.http)
# Poll for interactions (single hook)
interactions = client.poll(hook.id)
interactions.each do |interaction|
if interaction.dns?
puts "DNS query: #{interaction.data}"
elsif interaction.http?
puts "HTTP request: #{interaction.data}"
end
end
Batch Polling Example
When working with multiple hooks, use poll_batch for better performance:
require 'hookd'
require 'typhoeus'
# Initialize the client
client = Hookd::Client.new(
server: "https://hookd.example.com",
token: ENV['HOOKD_TOKEN']
)
# Register multiple hooks
puts "Registering 5 hooks..."
hooks = client.register(count: 5)
hook_ids = hooks.map(&:id)
puts "Created hooks: #{hook_ids.join(', ')}"
# Simulate some interactions...
# (make DNS queries, HTTP requests, etc.)
# Simulate some interactions
puts "\nSimulating HTTP requests..."
hooks.each do |hook|
Typhoeus.get(hook.http)
puts " ✓ GET #{hook.http}"
end
# Batch poll all hooks at once (1 HTTP request instead of 5)
puts "Batch polling #{hook_ids.size} hooks..."
results = client.poll_batch(hook_ids)
# Display results
results.each do |hook_id, result|
if result[:error]
puts "❌ Hook #{hook_id}: #{result[:error]}"
else
interactions = result[:interactions]
puts "✅ Hook #{hook_id}: #{interactions.size} interaction(s)"
interactions.each do |interaction|
if interaction.dns?
puts " - DNS: #{interaction.data['qname']} (#{interaction.data['qtype']})"
elsif interaction.http?
puts " - HTTP: #{interaction.data['method']} #{interaction.data['path']}"
end
end
end
end
Configuration
The client requires two configuration parameters:
server: The Hookd server URL (e.g.,https://hookd.example.com)token: Authentication token for API access
API Reference
Hookd::Client
Main client class for interacting with the Hookd server.
#register(count: nil)
Register one or more hooks and get DNS/HTTP endpoints.
Single hook (default):
hook = client.register
# => #<Hookd::Hook id="abc123" dns="abc123.hookd.example.com" ...>
Multiple hooks:
hooks = client.register(count: 5)
# => [#<Hookd::Hook id="abc123" ...>, #<Hookd::Hook id="def456" ...>, ...]
Parameters:
count(Integer, optional) - Number of hooks to create (default: 1)
Returns:
Hookd::Hookobject whencountis 1 or not specified- Array of
Hookd::Hookobjects whencount> 1
Raises:
ArgumentError- Invalid count parameterHookd::AuthenticationError- Authentication failedHookd::ServerError- Server error (5xx)Hookd::ConnectionError- Connection failed
#poll(hook_id)
Poll for interactions captured by a single hook.
interactions = client.poll("abc123")
# => [#<Hookd::Interaction type="dns" ...>, ...]
Parameters:
hook_id(String) - The hook ID to poll
Returns: Array of Hookd::Interaction objects
Raises:
Hookd::AuthenticationError- Authentication failedHookd::NotFoundError- Hook not foundHookd::ServerError- Server error (5xx)Hookd::ConnectionError- Connection failed
#poll_batch(hook_ids)
Batch poll - Poll for interactions from multiple hooks in a single request.
# Register multiple hooks
hooks = client.register(count: 3)
hook_ids = hooks.map(&:id)
# Batch poll all hooks at once (1 HTTP request instead of 3)
results = client.poll_batch(hook_ids)
# => {
# "abc123" => { interactions: [...], error: nil },
# "def456" => { interactions: [...], error: nil },
# "ghi789" => { interactions: [], error: nil }
# }
# Process results
results.each do |hook_id, result|
if result[:error]
puts "Error for #{hook_id}: #{result[:error]}"
else
puts "Hook #{hook_id}: #{result[:interactions].size} interactions"
result[:interactions].each do |interaction|
puts " - #{interaction.type}: #{interaction.data}"
end
end
end
Parameters:
hook_ids(Array) - Array of hook IDs to poll
Returns: Hash mapping hook IDs to results
- Each result contains:
interactions(ArrayHookd::Interaction) - Array of interactionserror(String, nil) - Error message if hook not found
Raises:
ArgumentError- Invalid hook_ids (not an array or empty)Hookd::AuthenticationError- Authentication failedHookd::ServerError- Server error (5xx)Hookd::ConnectionError- Connection failed
Benefits:
- Performance: Reduced latency with single HTTP request
- Efficiency: Automatic connection reuse with HTTPX
- Atomic: Consistent snapshot of all hooks
#metrics
Get server metrics (requires authentication).
metrics = client.metrics
# => {"total_hooks" => 42, "total_interactions" => 1337, ...}
Returns: Hash with metrics data
Hookd::Hook
Represents a registered hook with endpoints.
Attributes:
id(String) - Unique hook identifierdns(String) - DNS endpointhttp(String) - HTTP endpointhttps(String) - HTTPS endpointcreated_at(String) - Creation timestamp
Hookd::Interaction
Represents a captured DNS or HTTP interaction.
Attributes:
type(String) - Interaction type ("dns" or "http")timestamp(String) - When the interaction was captureddata(Hash) - Interaction details
Methods:
#dns?- Returns true if this is a DNS interaction#http?- Returns true if this is an HTTP interaction
Error Handling
The client raises specific exceptions for different error conditions:
begin
hook = client.register
rescue Hookd::AuthenticationError
puts "Invalid token"
rescue Hookd::ConnectionError => e
puts "Connection failed: #{e.message}"
rescue Hookd::ServerError => e
puts "Server error: #{e.message}"
end
Exception hierarchy:
Hookd::Error(base class)Hookd::AuthenticationError- 401 UnauthorizedHookd::NotFoundError- 404 Not FoundHookd::ServerError- 5xx Server ErrorHookd::ConnectionError- Network/connection errors