Reputation: 387
I am using Geo::IP
to perform location lookups on ip addresses. Everything works fine until I come across an ip address which is not in the geo ip lookup database and the program shuts abruptly giving this error
Can't call method "city" on an undefined value at script.pl line 16.
Current code looks like this
$gi = Geo::IP->open("/usr/local/share/GeoIP/GeoLiteCity.dat", GEOIP_STANDARD);
my $record = $gi->record_by_addr($key);
my $city= $record->city;
Any suggestions on how I can by pass this? It works perfectly fine until it hits an ip address that isn't defined within that module.
Upvotes: 0
Views: 751
Reputation: 9520
Looking at the Geo::IP source, if the IP address is not in the database, it returns undef
. Therefore, to bypass the problem, you can do:
my $record = $gi->record_by_addr($key);
## check that $record is defined
if ($record) {
my $city= $record->city;
...
}
else {
# issue an error message if wanted
warn "No record found for $key";
}
Relevant code from the Geo::IP source:
The function you're using is record_by_addr
. From the source, record_by_addr
is an alias for get_city_record_as_hash
(see perlref for the syntax used to create an 'alias' for a function):
*record_by_addr = \&get_city_record_as_hash;
The code for get_city_record_as_hash
is as follows:
#this function returns the city record as a hash ref
sub get_city_record_as_hash {
my ( $gi, $host ) = @_;
my %gir;
@gir{qw/ country_code country_code3 country_name region city
postal_code latitude longitude dma_code area_code
continent_code region_name metro_code / } =
$gi->get_city_record($host);
return defined($gir{latitude}) ? bless( \%gir, 'Geo::IP::Record' ) : undef;
}
This code runs get_city_record
using $host
, the IP address you supplied, as the argument. If get_city_record
finds a record, the data it returns populates the %gir
hash. The last line of the sub uses the [ternary form of if-else] to evaluate whether getting the record was successful, and to return the appropriate result. It checks whether $gir{latitude}
is defined, and if it is, it creates and returns a Geo::IP::Record
object from it (which you can query with methods like city
, etc.). If it isn't, it returns undef
.
A simpler way to view the last line would be this:
# is $gir{latitude} defined?
if (defined ($gir{latitude})) {
# yes: create a Geo::IP::Record object with the data in %gir
# return that object
return bless( \%gir, 'Geo::IP::Record' )
}
else {
# no: return undefined.
return undef;
}
Upvotes: 3
Reputation: 53478
I'd suggest that you need Data::Dumper
here, to tell you what's going on with $record
. I would guess that record_by_addr($key);
is the root of your problems, and that because $key
is in some way bad, $record
is undefined.
This would thus be fixed:
use Data::Dumper;
print Dumper \$record;
I'm guessing $record
will be undefined, and therefore:
next unless $record;
will skip it.
Upvotes: 1