Geo-Coder-GeoApify

 view release on metacpan or  search on metacpan

lib/Geo/Coder/GeoApify.pm  view on Meta::CPAN


    use Geo::Coder::GeoApify;

    my $geo_coder = Geo::Coder::GeoApify->new(apiKey => $ENV{'GEOAPIFY_KEY'});
    my $location = $geo_coder->geocode(location => '10 Downing St., London, UK');

=head1 DESCRIPTION

Geo::Coder::GeoApify provides an interface to https://www.geoapify.com/maps-api/,
a free Geo-Coding database covering many countries.

=over 4

=item * Caching

Identical geocode requests are cached (using L<CHI> or a user-supplied caching object),
reducing the number of HTTP requests to the API and speeding up repeated queries.

This module leverages L<CHI> for caching geocoding responses.
When a geocode request is made,
a cache key is constructed from the request.
If a cached response exists,
it is returned immediately,
avoiding unnecessary API calls.

=item * Rate-Limiting

A minimum interval between successive API calls can be enforced to ensure that the API is not overwhelmed and to comply with any request throttling requirements.

Rate-limiting is implemented using L<Time::HiRes>.
A minimum interval between API
calls can be specified via the C<min_interval> parameter in the constructor.
Before making an API call,
the module checks how much time has elapsed since the
last request and,
if necessary,
sleeps for the remaining time.

=back

=head1 METHODS

=head2 new

    $geo_coder = Geo::Coder::GeoApify->new(apiKey => $ENV{'GEOAPIFY_KEY'});

Creates a new C<Geo::Coder::GeoApify> object with the provided apiKey.

It takes several optional parameters:

=over 4

=item * C<cache>

A caching object.
If not provided,
an in-memory cache is created with a default expiration of one hour.

=item * C<host>

The API host endpoint.
Defaults to L<https://api.geoapify.com/v1/geocode>.

=item * C<min_interval>

Minimum number of seconds to wait between API requests.
Defaults to C<0> (no delay).
Use this option to enforce rate-limiting.

=item * C<ua>

An object to use for HTTP requests.
If not provided, a default user agent is created.

=back

=cut

sub new
{
	my $class = shift;

	# Handle hash or hashref arguments
	my %args = (ref($_[0]) eq 'HASH') ? %{$_[0]} : @_;

	# Ensure the correct instantiation method is used
	unless (defined $class) {
		carp(__PACKAGE__, ' Use ->new() not ::new() to instantiate');
		return;
	}

	# If $class is an object, clone it with new arguments
	return bless { %{$class}, %args }, ref($class) if ref($class);

	# Validate that the apiKey is provided and is a scalar
	my $apiKey = $args{'apiKey'};
	unless (defined $apiKey && !ref($apiKey)) {
		carp(__PACKAGE__, defined $apiKey ? ' apiKey must be a scalar' : ' apiKey not given');
		return;
	}

	# Set up user agent (ua) if not provided
	my $ua = $args{'ua'} // LWP::UserAgent->new(agent => __PACKAGE__ . "/$VERSION");
	$ua->default_header(accept_encoding => 'gzip,deflate');
	$ua->env_proxy(1);

	# Disable SSL verification if the host is not defined (not recommended in production)
	$ua->ssl_opts(verify_hostname => 0) unless defined $args{'host'};

	# Set host, defaulting to 'api.geoapify.com/v1/geocode'
	my $host = $args{'host'} // 'api.geoapify.com/v1/geocode';

	# Set up caching (default to an in-memory cache if none provided)
	my $cache = $args{cache} || CHI->new(
		driver => 'Memory',
		global => 1,
		expires_in => '1 day',
	);

	# Set up rate-limiting: minimum interval between requests (in seconds)
	my $min_interval = $args{min_interval} || 0;	# default: no delay



( run in 1.486 second using v1.01-cache-2.11-cpan-140bd7fdf52 )