Acme-Free-API-Geodata-GeoIP
view release on metacpan or search on metacpan
use strict;
use warnings;
use Acme::Free::API::Geodata::GeoIP;
my $ip = shift @ARGV;
if(!defined($ip)) {
die("Usage: geoip IPADDRESS");
}
my $agent = Acme::Free::API::Geodata::GeoIP->new(debug => 1);
my $geodata = $agent->lookup($ip);
if(!defined($geodata)) {
die("Lookup failed");
}
print "$ip is hosted by ", $geodata->{org}, " in ", $geodata->{city}, " (", $geodata->{country}, ")\n";
lib/Acme/Free/API/Geodata/GeoIP.pm view on Meta::CPAN
sub new($proto, %config) {
my $class = ref($proto) || $proto;
my $self = bless \%config, $class;
my $agent = WWW::Mechanize->new(cookie_jar => {});
$agent->agent('PerlMonks contest/1 (https://perlmonks.org/?node_id=11161472)');
$agent->stack_depth(1);
$self->{agent} = $agent;
if(!defined($self->{debug})) {
$self->{debug} = 0;
}
return $self;
}
sub lookup($self, $ip) {
my $url = "http://ip-api.com/json/" . $ip;
my $content = $self->_fetchURL($url);
my $ok = 0;
my $decoded;
eval {
$decoded = decode_json($content);
$ok = 1;
};
if(!$ok || !defined($decoded)) {
$self->_debuglog("Failed to decode response. Not a JSON document?");
$self->_debuglog(Dumper($decoded));
return;
}
#$self->_debuglog(Dumper($decoded));
return $decoded;
}
# internal helpers
# these are copied from CAVACs vast framework. But we don't want hundreds of dependencies in this example code, only a couple of functions
sub _fetchURL($self, $url) {
$self->{agent}->get($url);
if(!$self->{agent}->success()) {
$self->_debuglog("Network error while fetching URL $url");
return;
}
my $response = $self->{agent}->response();
if(!defined($response)) {
$self->_debuglog("Could not get agent response");
return;
}
my $content = $response->decoded_content;
if(!defined($content) || !length($content)) {
$self->_debuglog("Could not get response content");
return;
}
#$self->_debuglog(Dumper($content));
return $content;
}
sub _debuglog($self, $message) {
if(!$self->{debug}) {
return;
}
print STDERR $message, "\n";
}
1;
__END__
=head1 NAME
Acme::Free::API::Geodata::GeoIP - Lookup GeoIP data for an IP address
=head1 SYNOPSIS
use Acme::Free::API::Geodata::GeoIP;
my $agent = Acme::Free::API::Geodata::GeoIP->new(debug => 1);
my $geodata = $agent->lookup('24.48.0.1');
if(!defined($geodata)) {
die("Lookup failed");
}
print "$ip is hosted by ", $geodata->{org}, " in ", $geodata->{city}, " (", $geodata->{country}, ")\n";
=head1 DESCRIPTION
This module looks up GeoIP data through a public API, see L<https://www.freepublicapis.com/ip-geolocation-api>.
It returns a hashref on success, undefined on failure. To see what went wrong, set debug to a true value in new().
=head1 SEE ALSO
Call for API implementations on PerlMonks: L<https://perlmonks.org/?node_id=11161472>
=head1 AUTHOR
Rene Schickbauer, E<lt>cavac@cpan.orgE<gt>
=head1 SOURCECODE
t/Acme-Free-API-Geodata-GeoIP.t view on Meta::CPAN
#########################
# change 'tests => 1' to 'tests => last_test_to_print';
use strict;
use warnings;
use Test::More tests => 8;
BEGIN { use_ok('Acme::Free::API::Geodata::GeoIP') };
my $geoip = Acme::Free::API::Geodata::GeoIP->new(debug => 0);
ok(defined($geoip), 'Initialization');
my %map = (
'24.48.0.1' => 'Videotron',
'94.130.141.212' => 'Hetzner',
);
foreach my $ip (sort keys %map) {
my $org = $map{$ip};
( run in 1.086 second using v1.01-cache-2.11-cpan-49f99fa48dc )