Skip to content

Commit

Permalink
Merge pull request #31 from ipinfo/usama/ipv6-support
Browse files Browse the repository at this point in the history
IPv6 support
  • Loading branch information
UmanShahzad authored Jan 11, 2024
2 parents 735e47c + dc02829 commit 31f2aa4
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 24 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
./t
.vscode
69 changes: 50 additions & 19 deletions Geo-IPinfo/lib/Geo/IPinfo.pm
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ my %valid_fields = (
domains => 1,
);
my $base_url = 'https://ipinfo.io/';
my $base_url_ipv6 = 'https://v6.ipinfo.io/';
my $country_flag_url = 'https://cdn.ipinfo.io/static/images/countries-flags/';
my $cache_ttl = 0;
my $custom_cache = 0;
Expand Down Expand Up @@ -1060,8 +1061,9 @@ sub new {
my $self = {};
$token = defined $token ? $token : '';

$self->{base_url} = $base_url;
$self->{ua} = LWP::UserAgent->new;
$self->{base_url} = $base_url;
$self->{base_url_ipv6} = $base_url_ipv6;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->ssl_opts( 'verify_hostname' => 0 );
$self->{ua}->default_headers(
HTTP::Headers->new(
Expand Down Expand Up @@ -1113,15 +1115,23 @@ sub new {
sub info {
my ( $self, $ip ) = @_;

return $self->_get_info( $ip, '' );
return $self->_get_info( $ip, '', 0 );
}

#-------------------------------------------------------------------------------

sub info_v6 {
my ( $self, $ip ) = @_;

return $self->_get_info( $ip, '', 1 );
}

#-------------------------------------------------------------------------------

sub geo {
my ( $self, $ip ) = @_;

return $self->_get_info( $ip, 'geo' );
return $self->_get_info( $ip, 'geo', 0 );
}

#-------------------------------------------------------------------------------
Expand All @@ -1139,7 +1149,7 @@ sub field {
return;
}

return $self->_get_info( $ip, $field );
return $self->_get_info( $ip, $field, 0 );
}

#-------------------------------------------------------------------------------
Expand All @@ -1154,7 +1164,7 @@ sub error_msg {
#-- private method(s) below, don't call them directly -------------------------

sub _get_info {
my ( $self, $ip, $field ) = @_;
my ( $self, $ip, $field, $ipv6_lookup ) = @_;

$ip = defined $ip ? $ip : '';
$field = defined $field ? $field : '';
Expand All @@ -1167,7 +1177,7 @@ sub _get_info {
}
}

my ( $info, $message ) = $self->_lookup_info( $ip, $field );
my ( $info, $message ) = $self->_lookup_info( $ip, $field, $ipv6_lookup );
$self->{message} = $message;

if ( $field ne '' && ref($info) eq 'HASH' ) {
Expand All @@ -1181,14 +1191,16 @@ sub _get_info {
}

sub _lookup_info {
my ( $self, $ip, $field ) = @_;
my ( $self, $ip, $field, $ipv6_lookup ) = @_;

# checking bogon IP and returning response locally.
if ( _is_bogon($ip) ) {
my $details = {};
$details->{ip} = $ip;
$details->{bogon} = "True";
return ( $details, '' );
if ( $ip ne '' ) {
if ( _is_bogon($ip) ) {
my $details = {};
$details->{ip} = $ip;
$details->{bogon} = "True";
return ( $details, '' );
}
}

my $key = $ip . '/' . $field;
Expand All @@ -1198,7 +1210,7 @@ sub _lookup_info {
return ( $cached_info, '' );
}

my ( $source_info, $message ) = $self->_lookup_info_from_source($key);
my ( $source_info, $message ) = $self->_lookup_info_from_source($ipv6_lookup, $key);
if ( not defined $source_info ) {
return ( $source_info, $message );
}
Expand Down Expand Up @@ -1253,9 +1265,15 @@ sub _lookup_info_from_cache {
}

sub _lookup_info_from_source {
my ( $self, $key ) = @_;
my ( $self, $is_ipv6, $key ) = @_;

my $url = $self->{base_url} . $key;
my $url = '';
if ( $is_ipv6 ) {
$url = $self->{base_url_ipv6} . $key;
} else {
$url = $self->{base_url} . $key;
}

my $response = $self->{ua}->get($url);

if ( $response->is_success ) {
Expand Down Expand Up @@ -1388,8 +1406,13 @@ A quick usage example:
$ip_address = '216.239.36.21';
$details = $ipinfo->info($ip_address);
$city = $details->city; # Emeryville
$loc = $details->loc; # 37.8342,-122.2900
$city = $details->city; # Mountain View
$loc = $details->loc; # 37.4056,-122.0775
$ip_address = '2001:4860:4860::8888';
$details = $ipinfo->info_v6($ip_address);
$city = $details->city; # Mountain View
$loc = $details->loc; # 37.4056,-122.0775
=head1 SUBROUTINES/METHODS
Expand All @@ -1406,7 +1429,15 @@ if 'options' is specfied, the included values will allow control over cache poli
=head2 info(ip_address)
Returns a reference to a Details object containing all information related to the IP address. In case
Returns a reference to a Details object containing all information related to the IPv4 address. In case
of errors, returns undef, the error message can be retrieved with the function 'error_msg()'
The values can be accessed with the named methods: ip, org, domains, privacy, abuse, timezone, hostname, city, country, country_name, country_flag,
country_flag_url, country_currency, continent, is_eu, loc, latitude, longitude, postal, asn, company, meta, carrier, and all.
=head2 info_v6(ip_address)
Returns a reference to a Details object containing all information related to the IPv6 address. In case
of errors, returns undef, the error message can be retrieved with the function 'error_msg()'
The values can be accessed with the named methods: ip, org, domains, privacy, abuse, timezone, hostname, city, country, country_name, country_flag,
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,16 @@ $loc = $details->loc; # 37.8342,-122.2900

#### Usage

The `Geo::IPinfo->info()` method accepts an IP address as an optional, positional argument. If no IP address is specified, the API will return data for the IP address from which it receives the request.
The `Geo::IPinfo->info()` method accepts an IPv4 address as an optional, positional argument. If no IP address is specified, the API will return data for the IP address from which it receives the request. The `Geo::IPinfo->info_v6()` method works in a similar fashion but for IPv6 addresses.

```perl
use Geo::IPinfo;

$access_token = '123456789abc';
$ipinfo = Geo::IPinfo->new($access_token);
$details = $ipinfo->info($ip_address);
# for IPv6
# $details = $ipinfo->info_v6($ip_address);

if (defined $details) # valid data returned
{
Expand All @@ -90,7 +92,7 @@ $ipinfo = Geo::IPinfo->new($access_token);

#### Details Data

`Geo::IPinfo->info()` will return a `Details` object that contains all fields listed in the [IPinfo developer docs](https://ipinfo.io/developers/responses#full-response) with a few minor additions. Properties can be accessed through methods of the same name.
`Geo::IPinfo->info()` and `Geo::IPinfo->info_v6()` will return a `Details` object that contains all fields listed in the [IPinfo developer docs](https://ipinfo.io/developers/responses#full-response) with a few minor additions. Properties can be accessed through methods of the same name.

```perl
$hostname = $details->hostname; # cpe-104-175-221-247.socal.res.rr.com
Expand Down Expand Up @@ -193,7 +195,7 @@ $ipinfo = Geo::IPinfo->new($token, ("timeout" => 5));

#### Internationalization

When looking up an IP address, the `$details` object includes a `$details->country_name` method which includes the country name based on American English, `$details->is_eu` method which returns `true` if the country is a member of the European Union (EU) else `undef`, `$details->country_flag` method which returns a dictionary of emoji and Unicode of the country's flag, `$details->country_flag_url` will return a public link to the country's flag image as an SVG which can be used anywhere and `$details->country_currency` method which returns a dictionary of code, the symbol of a country's currency and `$details->continent` which includes code and name of the continent. It is possible to return the country name in other languages, change the EU countries, countries flags, countries' currencies, and continents by setting the `countries`, `eu_countries`, `countries_flags`, `countries_currencies` and `continents` settings when creating the `IPinfo` object. The `countries`, `countries_flags`, `countries_currencies`, and `continents` are hashes while `eu_countries` is an array.
When looking up an IP address, the `$details` object includes a `$details->country_name` method which includes the country name based on American English, `$details->is_eu` method which returns `true` if the country is a member of the European Union (EU) else `undef`, `$details->country_flag` method which returns a dictionary of emoji and Unicode of the country's flag, `$details->country_flag_url` will return a public link to the country's flag image as an SVG which can be used anywhere and `$details->country_currency` method which returns a dictionary of code, the symbol of a country's currency and `$details->continent` which includes code and name of the continent. It is possible to return the country name in other languages, change the EU countries, countries flags, countries' currencies, and continents by setting the `countries`, `eu_countries`, `countries_flags`, `countries_currencies` and `continents` settings when creating the `IPinfo` object. The `countries`, `countries_flags`, `countries_currencies`, and `continents` are hashes while `eu_countries` is an array.

```perl
my %custom_countries = (
Expand Down
16 changes: 14 additions & 2 deletions example.pl
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,20 @@
print $ipinfo->error_msg . "\n";
}

# you can also retrieve information for IPv6 addresses in a similar fashion
my $ipv6_data = $ipinfo->info_v6('2001:4860:4860::8888');
if ( defined $ipv6_data ) # valid data returned
{
# print JSON string
my $json = JSON->new->allow_blessed->convert_blessed;
my $json_string = $json->utf8->pretty->encode($ipv6_data);
print $json_string . "\n";
}
else # invalid data obtained, show error message
{
print $ipinfo->error_msg . "\n";
}

# retrieve only city information of the IP address
my $details = $ipinfo->field( '8.8.8.8', 'city' );

print "The city of 8.8.8.8 is " . $details->city . "\n";

0 comments on commit 31f2aa4

Please sign in to comment.