Class: Ipregistry::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/ipregistry/client.rb

Overview

Client for the Ipregistry API. A Client is safe for concurrent use by multiple threads.

client = Ipregistry::Client.new("YOUR_API_KEY")
info = client.lookup("8.8.8.8")
info.location.country.name # => "United States"

By default the client uses a 15-second timeout, retries transient failures up to three times, and performs no caching. Behavior is customized with keyword arguments to #initialize.

Constant Summary collapse

DEFAULT_BASE_URL =

Base URL of the Ipregistry API used unless overridden with base_url:.

"https://api.ipregistry.co"
MAX_BATCH_SIZE =

Maximum number of IP addresses Ipregistry accepts in a single batch request. #batch_lookup transparently splits larger arrays into several requests so callers never have to.

1024
DEFAULT_TIMEOUT =

seconds

15
DEFAULT_MAX_RETRIES =
3
DEFAULT_RETRY_INTERVAL =

seconds

1.0
DEFAULT_BATCH_CONCURRENCY =
4
USER_AGENT =

Default value of the User-Agent header sent with requests.

"IpregistryClient/Ruby/#{VERSION}".freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, retry_interval: DEFAULT_RETRY_INTERVAL, retry_on_server_error: true, retry_on_too_many_requests: false, cache: Cache::None.new, max_batch_size: MAX_BATCH_SIZE, batch_concurrency: DEFAULT_BATCH_CONCURRENCY, user_agent: USER_AGENT) ⇒ Client

Creates a client authenticating with the given API key. You can obtain a key, along with a generous free tier, at https://ipregistry.co.

Parameters:

  • api_key (String)

    your Ipregistry API key

  • base_url (String) (defaults to: DEFAULT_BASE_URL)

    overrides the API base URL, mainly useful for testing or pointing at a private deployment

  • timeout (Numeric) (defaults to: DEFAULT_TIMEOUT)

    per-request timeout in seconds, applied to connection open, read, and write (default 15)

  • max_retries (Integer) (defaults to: DEFAULT_MAX_RETRIES)

    maximum number of automatic retries performed in addition to the initial attempt; 0 disables retries (default 3)

  • retry_interval (Numeric) (defaults to: DEFAULT_RETRY_INTERVAL)

    base backoff in seconds between retries; successive retries use an exponentially increasing delay (interval * 2^attempt), and a 429 response carrying a Retry-After header takes precedence (default 1)

  • retry_on_server_error (Boolean) (defaults to: true)

    whether 5xx responses are retried (default true); transient network errors are always retried

  • retry_on_too_many_requests (Boolean) (defaults to: false)

    whether 429 Too Many Requests responses are retried, honoring the Retry-After header when present. Ipregistry does not rate limit by default (it is opt-in per API key), so this defaults to false

  • cache (Object) (defaults to: Cache::None.new)

    response cache; disabled by default so that data is never stale. Pass an Ipregistry::Cache::Memory instance or any object with the same interface

  • max_batch_size (Integer) (defaults to: MAX_BATCH_SIZE)

    maximum number of IP addresses sent in a single batch request, capped at MAX_BATCH_SIZE (the API limit)

  • batch_concurrency (Integer) (defaults to: DEFAULT_BATCH_CONCURRENCY)

    how many batch sub-requests #batch_lookup dispatches concurrently when an array is large enough to be split into chunks; 1 means strictly sequential dispatch, which is gentler on a rate-limited API key (default 4)

  • user_agent (String) (defaults to: USER_AGENT)

    overrides the User-Agent header sent with requests

Raises:

  • (ArgumentError)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/ipregistry/client.rb', line 82

def initialize(api_key,
               base_url: DEFAULT_BASE_URL,
               timeout: DEFAULT_TIMEOUT,
               max_retries: DEFAULT_MAX_RETRIES,
               retry_interval: DEFAULT_RETRY_INTERVAL,
               retry_on_server_error: true,
               retry_on_too_many_requests: false,
               cache: Cache::None.new,
               max_batch_size: MAX_BATCH_SIZE,
               batch_concurrency: DEFAULT_BATCH_CONCURRENCY,
               user_agent: USER_AGENT)
  raise ArgumentError, "api_key must not be nil or empty" if api_key.nil? || api_key.to_s.strip.empty?

  @api_key = api_key.to_s
  @base_url = base_url.to_s.sub(%r{/+\z}, "")
  @timeout = timeout
  @max_retries = [max_retries.to_i, 0].max
  @retry_interval = retry_interval
  @retry_on_server_error = retry_on_server_error
  @retry_on_too_many_requests = retry_on_too_many_requests
  @cache = cache || Cache::None.new
  @max_batch_size = max_batch_size.to_i.clamp(1, MAX_BATCH_SIZE)
  @batch_concurrency = [batch_concurrency.to_i, 1].max
  @user_agent = user_agent
end

Instance Attribute Details

#base_urlString (readonly)

Returns the API base URL.

Returns:

  • (String)

    the API base URL



48
49
50
# File 'lib/ipregistry/client.rb', line 48

def base_url
  @base_url
end

#cacheObject (readonly)

Returns the cache used by the client.

Returns:

  • (Object)

    the cache used by the client



45
46
47
# File 'lib/ipregistry/client.rb', line 45

def cache
  @cache
end

Instance Method Details

#batch_lookup(ips, fields: nil, hostname: nil, **params) ⇒ BatchResponse

Resolves several IP addresses at once. The returned BatchResponse preserves the order of ips, and each entry may independently succeed or fail; a raised error indicates the whole request failed (for example authentication or a network error), not the failure of an individual entry.

The Ipregistry API accepts up to MAX_BATCH_SIZE addresses per request; larger arrays are transparently split into several requests dispatched with bounded concurrency (see max_batch_size: and batch_concurrency:) and reassembled in input order.

Entries already present in the cache are served locally; only the remainder are requested from the API, and freshly resolved entries are cached. Accepts the same keywords as #lookup.

Parameters:

  • ips (Array<String, IPAddr>)

    the IP addresses to look up

Returns:

Raises:



172
173
174
175
176
177
178
179
180
181
# File 'lib/ipregistry/client.rb', line 172

def batch_lookup(ips, fields: nil, hostname: nil, **params)
  ips = Array(ips).map { |ip| ip.to_s.strip }
  query = build_query(fields: fields, hostname: hostname, **params)

  cached = ips.map { |ip| @cache.get(cache_key(ip, query)) }
  misses = ips.zip(cached).reject { |_, hit| hit }.map(&:first)
  fresh = resolve_misses(misses, query)

  BatchResponse.new(assemble_batch_results(ips, cached, fresh, query))
end

#lookup(ip, fields: nil, hostname: nil, **params) ⇒ Models::IpInfo

Returns the data associated with the given IP address. The ip argument must be a non-empty IPv4 or IPv6 address (String or IPAddr); to look up the requester's own IP, use #lookup_origin instead.

When a cache is configured, a hit is returned without contacting the API.

Parameters:

  • ip (String, IPAddr)

    the IP address to look up

  • fields (String, nil) (defaults to: nil)

    restricts the response to the given fields, using Ipregistry's field selector syntax (for example "location.country.name,security"). This reduces payload size and, in some cases, credit usage. See https://ipregistry.co/docs/filtering-selecting-fields

  • hostname (Boolean, nil) (defaults to: nil)

    enables reverse-DNS hostname resolution (disabled by default)

  • params (Hash)

    arbitrary extra query parameters not covered by a dedicated keyword

Returns:

Raises:



127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/ipregistry/client.rb', line 127

def lookup(ip, fields: nil, hostname: nil, **params)
  ip = ip.to_s.strip
  raise ArgumentError, "ip must not be empty; use #lookup_origin for the requester IP" if ip.empty?

  query = build_query(fields: fields, hostname: hostname, **params)
  key = cache_key(ip, query)
  cached = @cache.get(key)
  return cached if cached

  info = Models::IpInfo.new(request_json(:get, url_for(ip, query)))
  @cache.set(key, info)
  info
end

#lookup_origin(fields: nil, hostname: nil, **params) ⇒ Models::RequesterIpInfo

Returns the data associated with the IP address the request originates from, enriched with parsed User-Agent data. Origin lookups are never cached, because the requester IP is only known from the response.

Accepts the same keywords as #lookup.



149
150
151
152
# File 'lib/ipregistry/client.rb', line 149

def lookup_origin(fields: nil, hostname: nil, **params)
  query = build_query(fields: fields, hostname: hostname, **params)
  Models::RequesterIpInfo.new(request_json(:get, url_for("", query)))
end

#parse_user_agents(*user_agents) ⇒ BatchResponse

Parses one or more raw User-Agent strings (such as the User-Agent header of an incoming HTTP request) into structured data. Results preserve the order of the input.

response = client.parse_user_agents("Mozilla/5.0 ...")
response[0].value!.name # => "Chrome"

Parameters:

  • user_agents (Array<String>)

    the User-Agent strings to parse

Returns:

Raises:



193
194
195
196
197
# File 'lib/ipregistry/client.rb', line 193

def parse_user_agents(*user_agents)
  body = JSON.generate(user_agents.flatten.map(&:to_s))
  data = request_json(:post, "#{@base_url}/user_agent", body: body)
  BatchResponse.new(parse_batch_results(data) { |entry| Models::UserAgent.new(entry) })
end